Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fix 3d shadowcasting #32012

Closed
wants to merge 17 commits into from

Conversation

ifreund
Copy link
Contributor

@ifreund ifreund commented Jun 30, 2019

Summary

SUMMARY: Bugfixes "Fix bugs and increase performance of 3D shadowcasting"

Purpose of change

I'm attempting to revive #30861 as Kevin is busy with other performance work. Much of this is directly copied from that PR.

Fixes #6821
BOUNTY

3D shadowcasting has a number of rendering bugs remaining, fix them.
A non-exhaustive list:

  • As in Attacks from under ceiling with 3D FOV on. #29175 shockers are sometimes able to see and target you through a floor. With some debugging Kevin determined the cause to be 3D shadowcasting. Was caused by map shifts apparently.
  • When standing cardinally adjacent to a single opaque tile (wall or adult tree, etc), in 2D shadowcasting the area behind the tree is obscured, but in 3D it is visible.
    UPDATE: seems to be fixed with the slope struct.
  • When standing adjacent to a wall corner, in 2D shadowcasting the first tile of the wall is visible and the rest is occluded, in 3D the entire wall and anything behind it is visible.
    UPDATE: seems to be fixed with the slope struct.
  • 3D shadowcasting does not cast directly up or down, so there's a shadow directly above and below the player.
    UPDATE: Now fixed. We cast on 8 new octants, 4 up and 4 down.

Describe the solution

This is going to be a progressive process since I don't know what the problem is.

  • Extend shadowcasting test to trigger 3D shadowcasting and test 3D scenarios.
  • Add tests that characterize the breakage.
  • Replace recursive shadowcasting with iterative shadowcasting as outlined in Further shadowcasting optimizations #23373. In addition to being more performant, this should be easier to analyze and test.
  • Fix an infinite loop that pops up in some cases.
  • Fix the remaining bugs.
  • Cast straight up and down

@ifreund ifreund added Code: Performance Performance boosting code (CPU, memory, etc.) Z-levels Levels below and above ground. [C++] Changes (can be) made in C++. Previously named `Code` <Bugfix> This is a fix for a bug (or closes open issue) labels Jun 30, 2019
@ifreund ifreund force-pushed the fix-3d-shadowcasting-2 branch from 83bf5d0 to 5e031a2 Compare July 4, 2019 18:37
@ifreund
Copy link
Contributor Author

ifreund commented Jul 4, 2019

Quick update, I've corrected most of the major bugs and the new iterative 3d FOV is now totally playable and quite a bit more correct that the current recursive algorithm.

The only major todo item I'm currently aware of is doing something about casting straight up/down as we currently don't do that at all (That's the only test failing on travis currently).

@ifreund ifreund force-pushed the fix-3d-shadowcasting-2 branch 3 times, most recently from e7d0a5f to f83913b Compare July 5, 2019 11:24
@ifreund ifreund marked this pull request as ready for review July 5, 2019 11:25
T( *calc )( const T &, const T &, const int & ),
bool( *check )( const T &, const T & ),
T( *accumulate )( const T &, const T &, const int & )>
void cast_vertical_zlight_segment(
Copy link
Contributor Author

@ifreund ifreund Jul 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting cast_zlight_segment into vertical and horizontal versions isn't ideal and duplicates a lot of complex code. However, the alternative is some quite nasty iteration logic to handle the full range of possible coordinate transformations instead of the subset currently handled. Splitting it like this makes this already complex code a good bit more readable without the extra conditionals.

Would definitely appreciate feedback on whether this choice makes sense to others though.

Copy link
Contributor

@jbytheway jbytheway Jul 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's certainly possible to merge the horizontal and vertical versions of the algorithm. You'd want to abstract out the coordinate system more into some type template argument that would replace the various _transform numbers. Each version of that type would have methods to do the various transformations needed (between depth/major/minor coordinates and x/y/z coordinates).

I think it is worth doing and would probably help clarity and maintainability, but it doesn't have to be on this first PR.

@ifreund
Copy link
Contributor Author

ifreund commented Jul 5, 2019

3d shadowcasting now casts directly up and down, with a total of 8 more casts than the previous method. This means no more pyramid of unseen tiles directly above and below the player.

Performance impact shouldn't be too bad, as downward casts will almost always end immediately as they encounter the opaque ground and upward casts will either end immediately if under a roof or end much sooner than horizontal casts due to our rather low maximum z level.

So, upwards casting will be a slight slowdown when outdoors, but allows the player to see all the tiles they are supposed to see. The optimization described in #23914 or something like it would make upward casting trivial in most cases as the area above the player is usually either blocked by a roof or completely open.

@ifreund ifreund force-pushed the fix-3d-shadowcasting-2 branch 2 times, most recently from 07765bf to dcd3607 Compare July 5, 2019 14:20
}
}

int rise;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun fact, the shadowcasting area is only 60 deep and 60 wide, so rise and run can be 8-bit.
probably int_least8_t or uint_least8_t

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I had meant to go back and revise that but forgot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have negative slopes in some valid cases, so I'll be using int_least8_t

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I think int_least8_t is probably overkill. Cataclysm is already not going to work on any system where that isn't the same as int8_t.

@ZhilkinSerg ZhilkinSerg self-assigned this Jul 6, 2019
@ifreund
Copy link
Contributor Author

ifreund commented Jul 6, 2019

Need to figure out if int_fast8_t would be better for this use case, but that is non-trivial to profile properly and is an small change if needed.

Travis is complaining about a memory leak and I'm not quite sure how that could have happened as a result of these changes, but I'll do some more digging.

@ifreund
Copy link
Contributor Author

ifreund commented Jul 6, 2019

Clany tidy error is unrelated, I'd say this is good to go.

@ZhilkinSerg
Copy link
Contributor

Jenkins rebuild.

@esotericist
Copy link
Contributor

So, I merged this locally to do some playtests, and there's some kinda weird behavior here with view distance in reduced vision situations. I first noticed it while in a vehicle, but I was able to reproduce it in a building.

Details: it's 5:16 AM, with "drizzle" weather. So it's "very dark" outside.

Default vision (3d fov off) while in vehicle:
default vision in vehicle

After turning on 3d fov, and moving (to reset visible tiles):
3d fov in vehicle

Here's the difference between not-3d-fov and yes-3d-fov in the building (also involving steps in between to reset visible tiles):

default vision in building

3d fov in building

For extra bonus weird, I noticed view distance changing as I moved within the building. These next two shots are still with 3d fov on, as I step towards the door:

approaching door

approaching door more

The behavior reverses as I move back to my original position.

Extra extra extra bonus weird: what happens if I move one tile to the right, to sit in the chair:

image

That last one at least matches the default vision algorithm

@jbytheway
Copy link
Contributor

I had to turn off one of the vision tests on 3D because of the inconsistencies. Please turn that back on (indeed, you can totally rip out the feature of being able to turn off particular tests in 3D mode).

Copy link
Contributor

@jbytheway jbytheway left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good in terms of code quality. I haven't tested it, and the above examples indicate some changes from the previous algorithm, which should be investigated.

I'd like to see the vision tests generalized to 3D as well as the shadowcasting tests. The shadowcasting tests only test the boolean "is it visible at all", whereas the vision tests get into questions like "how visible is it?". I'd like us to be able to verify that there aren't any artefacts at the boundaries between the horizontal and vertical casting algorithms (e.g. look three levels up, is there an obvious 6x6 square where stuff looks different). Not vital that those be added in this PR, though.

src/shadowcasting.cpp Outdated Show resolved Hide resolved
src/shadowcasting.cpp Outdated Show resolved Hide resolved
T( *calc )( const T &, const T &, const int & ),
bool( *check )( const T &, const T & ),
T( *accumulate )( const T &, const T &, const int & )>
void cast_vertical_zlight_segment(
Copy link
Contributor

@jbytheway jbytheway Jul 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's certainly possible to merge the horizontal and vertical versions of the algorithm. You'd want to abstract out the coordinate system more into some type template argument that would replace the various _transform numbers. Each version of that type would have methods to do the various transformations needed (between depth/major/minor coordinates and x/y/z coordinates).

I think it is worth doing and would probably help clarity and maintainability, but it doesn't have to be on this first PR.

@ifreund
Copy link
Contributor Author

ifreund commented Jul 8, 2019

I believe my most recent commit has fixed that bug @esotericist, at least I can't reproduce it anymore. Thanks for testing!

@jbytheway
Copy link
Contributor

I believe my most recent commit has fixed that bug @esotericist, at least I can't reproduce it anymore. Thanks for testing!

Did you ensure we have a test that captures that failure mode before fixing it?

@ifreund
Copy link
Contributor Author

ifreund commented Jul 8, 2019

Did you ensure we have a test that captures that failure mode before fixing it?

Unfortunately I haven't been able to setup a test case that consistently passes after the change and fails before it, since the failure case is very sensitive to lighting. I've tried setting the weather before the test and doing the test several z levels underground. I can get it to behave properly 4/5 times or so, but haven't managed to track down the inconsistency yet.

@kevingranade
Copy link
Member

This looks not-right...
2019-07-09-070254_1366x768_scrot
2019-07-09-070300_1366x768_scrot
2019-07-09-070303_1366x768_scrot
2019-07-09-070311_1366x768_scrot
2019-07-09-070314_1366x768_scrot
2019-07-09-070317_1366x768_scrot

@ifreund
Copy link
Contributor Author

ifreund commented Jul 9, 2019

Went to the same location and could only reproduce half of the bug. You sure you had 96abcad included in that build?

Screenshots

Screen Shot 2019-07-09 at 10 06 06 AM
Screen Shot 2019-07-09 at 10 06 18 AM
Screen Shot 2019-07-09 at 10 06 25 AM
Screen Shot 2019-07-09 at 10 06 30 AM

ifreund added 4 commits July 9, 2019 16:28
and remove the code that allows disabling it
It somehow took me until now to realize that y coordinates are counted
from the "top" of the screen not the bottom, so fix the comment
diagrams
@ifreund ifreund force-pushed the fix-3d-shadowcasting-2 branch from 5289562 to 0ae920b Compare July 9, 2019 14:30
@ifreund
Copy link
Contributor Author

ifreund commented Jul 9, 2019

Marking this WIP for now as there's still a reproducible bug with it that I haven't managed to track down yet. In the process of debugging I found some faulty logic that may be partially at fault and am in the process of reworking how spans get split.

@ifreund ifreund changed the title Fix 3d shadowcasting [WIP] Fix 3d shadowcasting Jul 9, 2019
@ZhilkinSerg ZhilkinSerg removed their assignment Jul 13, 2019
@ifreund ifreund force-pushed the fix-3d-shadowcasting-2 branch from 4403e33 to 494a33b Compare July 14, 2019 13:11
@ThomasLinkin
Copy link

so this is abandoned i suppose?

@esotericist
Copy link
Contributor

so this is abandoned i suppose?

Not abandoned, merely stalled. The people with the appropriate expertise have been dealing with other matters, be it within the project or things outside of the project.

This will get tended to eventually.

@ifreund
Copy link
Contributor Author

ifreund commented Sep 28, 2020

Superseded by 42835

@Brambor
Copy link
Contributor

Brambor commented Nov 25, 2023

Superseded by #42835

Add # so that I can click it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
<Bugfix> This is a fix for a bug (or closes open issue) [C++] Changes (can be) made in C++. Previously named `Code` Code: Performance Performance boosting code (CPU, memory, etc.) Z-levels Levels below and above ground.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3-dimensional Z-level support, Core Part 3: FOV calculation. [$250]
7 participants