Cataclysm-BN icon indicating copy to clipboard operation
Cataclysm-BN copied to clipboard

Draw lower z levels

Open joveeater opened this issue 1 year ago • 8 comments

Summary

SUMMARY: Features "Draw in lower z levels."

Purpose of change

Fixes #1728. Draws in the contents of lower z levels with a visual effect.

Describe the solution

When drawing tiles previously each row would be collected and then drawn in turn. Now the whole map is collected first. It's during this collection that the searching down to lower z levels happens and only the lowest tile is collected. Collected tiles are sorted by z level, then the terrain, furniture, graffiti and trap layers are drawn for each collected tile in turn. Then starting at the lowest z level and working up, the fields, items, vehicles and creatures are drawn for each collected tile and the tiles above them. Lastly the zone markers and revival indicators are drawn.

Things being drawn on lower z levels have an effect applied to them. Similar to the greyscale and nightvision versions of sprites, a filter is applied that maintains the alpha channel and sets the color to a light cyan. When drawing the sprite this texture is drawn over the top of it using SDL_SetTextureAlphaMod to control transparency based on z level. There's an option to use a prebaked version of this with a fixed transparency instead.

When 3d field of view is turned on it takes into account visibility when looking downwards. If you don't have visibility on the tile below it will draw a small square like it does currently. This is also the case if you turn z levels off. When vehicles are being viewed from above like this they will prefer to show their roof part unless they have a creature in them.

Describe alternatives you've considered

Porting to UE5.

Testing

There are some cases that don't layer nicely. If a large sprite like a hulk is stood one tile south and down from a vehicle the hulk will be rendered below the vehicle making it look like it's shoved its head beneath it. I don't think this is easily resolved though. In this case the hulk should be on top, but if the vehicle covered a tile south as well, then it should be underneath as the vehicle should hide it entirely.

I'm not too happy with the way 3d fov looks, I think the squares look a bit out of place but flat cyan doesn't look any better. It also doesn't show car roofs as you can't see the tile with the part in it.

Additional context

Landed on a roof: chopnoz

Same with 3d fov on: chopz

joveeater avatar Jul 19 '22 05:07 joveeater

there's this beige path being left behind, i guess it has something to do with remembered maps.

https://user-images.githubusercontent.com/54838975/179726442-431f404a-24df-49a5-b34d-85db37b0e37c.mp4

scarf005 avatar Jul 19 '22 09:07 scarf005

Alright, that bug is fixed along with better handling for memory in general. Turns out memory was just ignoring the z value of the tripoints you gave it. That's no longer the case when z levels are on.

I fixed another bug that changing the option after the tileset was loaded caused misrendering. This behavior of force reloading the tileset when it changes has also been added to the map memory serpia/greyscale option so that it no longer requires you to restart.

joveeater avatar Jul 21 '22 17:07 joveeater

Wow <3 Definitely worth porting back to CDDA

Zireael07 avatar Jul 22 '22 10:07 Zireael07

Looks good, I just need some time to understand how it works to be able to tell if there are edge cases that need specific testing. There is minor merge conflict in one of the files.

Performance: I see that you avoid re-drawing the tiles in some way. Does this make drawing time mostly independent on z-level difference? If not, an option to limit how far does drawing below go would be useful.

Minor code quality tips:

  • Use get_map over g->m where possible. If re-used multiple times, it's good to save it in a temporary, usually map &here = get_map();. This helps with refactoring and avoids dependence on bloated game.h.
  • If you're reusing one option a lot, it's a good idea to cache it. cached_options.h has all the cached options and they are actually set in options.h. If you're reusing it only a moderate amount, using static strings (make_static.h and STATIC( "string_here" )) helps avoid rebuilding the string every invocation.

Coolthulhu avatar Jul 23 '22 11:07 Coolthulhu

Does this make drawing time mostly independent on z-level difference?

Yes, with the dynamic effect, 0 z levels is faster than 1 but 1 isn't faster than 7. The difference is a little more than 2x but this isn't going to be enough to impact most graphics hardware even phones.

That said the effect is capped at 7 z levels for visual reasons. The way it works is each z level is worth ~9% (24/256) opacity, except the first which is worth twice that much. This caps at 75% at 7 levels because higher opacity just makes it look like everything's been covered in blue paint.

joveeater avatar Jul 24 '22 18:07 joveeater

There's another bug with map memory: it's not rendered if it's outside character sight range bounds + there is no tile memorized at character's z-level. Example pics from an apartment tower with save:

Spoiler

render-lower-mmem-draw-bug.zip image image

Upd: this is on ver. 752b8605, before the force-push a few minutes ago.

olanti-p avatar Jul 24 '22 18:07 olanti-p

Good catch! I've done better handling for things outside of the map bounds. It's a bit of an awkward case as with that part of the map being unloaded we don't know where the floor is. As such it won't go lower than z level 0 in those cases to stop labs etc showing up above ground.

joveeater avatar Jul 26 '22 18:07 joveeater

also, could you push instead of force-push? following commits step by step would be easier to read

scarf005 avatar Jul 27 '22 02:07 scarf005

I'm getting weird edge lines with 3D vision: Screenshot from 2022-08-28 19-47-40

Those are seen as "below: grass", but rendered as dots.

There is a balance issue in that it lets player see the monsters below, but not the other way around. The simplest way to handle it would be to only render terrain, furniture and vehicles (stuff that is currently in map memory). I'm sure people will ask about V menu not showing the items that are below, so hiding items would be good.

Ideally, it would only show what player can see (in 3D), could see and remember (2D) and has actually remembered.

Other than those, I've seen no issues with it.

If it worked with map memory, we could allow player to look up/down in look mode. It's currently disabled if 3D view is disabled, but this means that player can't even review memory.

Coolthulhu avatar Aug 28 '22 18:08 Coolthulhu

How does it apply to ASCII?

RelMayers avatar Sep 01 '22 20:09 RelMayers

How does it apply to ASCII?

Right now it doesn't seem to apply at all. It should maintain parity. I'm not sure if the PR should be delayed until ASCII/tiles work the same way.

Still, monsters and items being shown graphically but "not truly seen" is certainly a blocker.

Coolthulhu avatar Sep 03 '22 11:09 Coolthulhu

The edge lines were caused by seeing some tiles from that stack without being able to see the ground. To fix it you can now have half-remembered tiles. That is tiles where you're remembering the terrain and then actually seeing a presumably flying monster on top.

I've also removed the ability to see items and monsters in 2d however, it still doesn't have total parity with ASCII. ASCII only lets you see down a single z level and getting rid of that because it's not great for flying is part of the intention. So I'd like to go the other way and bring ASCII to parity with this.

joveeater avatar Sep 06 '22 23:09 joveeater

2D vision, some item bits are still drawn: Screenshot from 2022-09-09 20-56-52

This message is now more misleading than before: Screenshot from 2022-09-09 21-02-58

It would be good to rephrase it to imply it's on the same level/story/[insert non-technical synonym for z coord].

Coolthulhu avatar Sep 09 '22 19:09 Coolthulhu

I've fixed the final layers (i.e. revival indicators and zone markers) using the wrong source, they now use the player's z level rather than the terrain's.

Also rather than change the message on the items, I've made it so you can now just see them across z levels same as you can with monsters.

joveeater avatar Sep 14 '22 11:09 joveeater

Also rather than change the message on the items, I've made it so you can now just see them across z levels same as you can with monsters.

That's a nice bonus!

Alright, let's give it a go.

Coolthulhu avatar Sep 15 '22 20:09 Coolthulhu

Can this be backported to DDA?

Zireael07 avatar Sep 16 '22 07:09 Zireael07