diasurgical / devilutionX

Diablo build for modern operating systems
Other
8.1k stars 796 forks source link

[Enhancement Proposal] Fix badly rendered shadows on common objects. #2451

Open NikoVP opened 3 years ago

NikoVP commented 3 years ago

This applies to all versions of Diablo

The graphics "bug" has been part of the game since release. Although the game is based on 3d models, the creators have used unorthodox method that generates shadows for objects. The sprites themselves are painted black and transformed to create the "shadow" and then combined it with the normal sprite. This method works some of the time, but in other cases its quite obvious that the result isn't true to what a properly rendered shadow is. Now finally after all these years we are at a point where correcting this is feasible. I have created a series of masks and new shadows that can be used to cutout the old and apply the new, leaving us with graphics the way they were supposed to be. Of course there are many more cases in player, objects, monster sprites, but these are some of the most obvious cases.

Just go and see all the chests, sarcophagus and weapons stands.

The graphics should contain correct shadows, not appearing out from the light source angle.

image

Proposal: I would gladly do all of it but I lack the programming skills. hence I am looking for collaborator here. A volunteer should use the masks and shadows provided in the file below to modify the existing graphics. The provided graphic files are based on the PNG extracted version of the graphics, I believe that they should have the same pixel dimensions as the original CEL files. Further conversion of the files might be needed, to make them compatible with the current capabilities of the engine. Masks and shadows files should not have copyright problems for distribution, so they can become part of the devilutionx.mpq data file.

image

Here is a zip file containing all the masks and new shadows for all chests, cathedral sarcophagus and weapon stands.

Objects Ready.zip

AJenbo commented 3 years ago

Co incidentally an issue with the render order of the original game caused this to be most hidden from the player as all sprites would effectively result in the following masking: image image

AJenbo commented 3 years ago

There are tow options for doing this.

1: Make the sprite type that uses SDL_Surface rather then CEL, on loading of the affected sprites covert the cel to an SDL_Surface and apply the mask.

2: Make a routine that can rencode the CEL data to change the transparent pixels, this is a bit tricky as this is done via the RLE compression.

I greatly favor option 1 and that would also make the game able to render sprites loaded from other format very easily.

glebm commented 3 years ago

I'm concerned about the increased memory usage of using SDL_Surface throughout (option 1). It'd be good if this was implemented as an option. Luckily, we now use the CelSprite wrapper class throghout, so that should be feasible.

AJenbo commented 3 years ago

@glebm what if we make sure to enable RLE compression for the SDL surfaces https://wiki.libsdl.org/SDL_SetSurfaceRLE ? I would think that should bring there size very close to that of CEL.

that being said i did intend for this to live along side the cel format and only be used when relevant

glebm commented 3 years ago

Yeah, RLE should be close to CEL. CL2 also has a "fill-N" command which SDL RLE does not, which might make a difference.

Not sure if SDL supports masked blits. If not, there is not much difference in implementing it for CEL vs CL2.

FitzRoyX commented 3 years ago

It's worth noting that sprites commonly make use of solid black, so the shadow cannot be accurately separated from them. You'd just be guessing where each begins and ends. There are 10k+ sprites. I'd consider this a huge timesink for a problem almost no one notices and has only an inconsistent solution at best.

nickgavran commented 3 years ago

It's worth noting that sprites commonly make use of solid black, so the shadow cannot be accurately separated from them.

Hey, can you provide an example of this, because I am very confident this is not true at all. If sprites "commonly" used solid black, it would mean that the trn/pal files could also translate the black shadow into other colors, and this does not occur in any part of the game. I scoured many sprites that look solid black, and the only ones to truly use a black color with the values '000000' (same as the shadow), is Tremain the Priest (which is an unused sprite), Town Portal, and small bits of the Rogue in heavy armor, as well as the succubus from certain angles

4 sprites is hardly "common", but it does prove a point that it won't work everywhere.

FitzRoyX commented 3 years ago

Well, you're right that it's not common, so I take that part back. The sprite colors are so dark that it's hard to tell without manipulating the brightness higher. I was poking at the rogue boots when I made that assumption.

NikoVP commented 3 years ago

Nothing in this method affects sprite colours or palettes, Masks affect what parts of the image is displayed by effectively subtracting/removing all information that we don't need. See using masks in Photoshop or other graphics editor to have an idea how the method works. All I've done is to provide the 'needed parts for the repairwork' and point the problem. The bad shadows of the chests are more or less visible depending on the terrain. Sarcophagus and weapon stands have more noticeable deviation from the norm. Again it all depends how it's implemented, and if someone is willing to invest the time.

julealgon commented 3 years ago
@nickgavran this is what I meant back in discord when I mentioned the shadows looked wrong to me: Vanilla Proposed
image image

At the time, you said the left part of the shadow (in the pick above) looked fine, while I said it looked incorrect to me.

The proposal looks a lot more "correct" to me (even though I can't really explain it properly 😆 )

julealgon commented 3 years ago

There are tow options for doing this.

1: Make the sprite type that uses SDL_Surface rather then CEL, on loading of the affected sprites covert the cel to an SDL_Surface and apply the mask.

2: Make a routine that can rencode the CEL data to change the transparent pixels, this is a bit tricky as this is done via the RLE compression.

I greatly favor option 1 and that would also make the game able to render sprites loaded from other format very easily.

Or option 3: make this a part of the installation process (which currently doesn't exist 🤣 )

nickgavran commented 3 years ago

@nickgavran this is what I meant back in discord when I mentioned the shadows looked wrong to me:

Vanilla Proposed image image At the time, you said the left part of the shadow (in the pick above) looked fine, while I said it looked incorrect to me.

The proposal looks a lot more "correct" to me (even though I can't really explain it properly 😆 )

The proposal looks better, as the shadow is actually coming from the correct angle there. The shadow we currently have looks fine to me when the sarcophagus is OPEN, maybe I didn't clarify this on discord. Oh well

glebm commented 1 year ago

These days the best option would probably be to apply the masks during CLX conversion. This can be done in the engine at load time, and in https://github.com/diasurgical/devilutionx-mpq-tools/ for low-RAM builds.

donatj commented 1 year ago

If this is “fixed” can it be optional as the original shadows are perhaps part of the charm for some people?

AJenbo commented 1 year ago

If this is “fixed” can it be optional as the original shadows are perhaps part of the charm for some people?

The original cut them because of overdraw, so it's not an original charm, see https://github.com/diasurgical/devilutionX/issues/2451#issuecomment-885979314

beelzebub draws them the same way we do, so maybe that is what you could be confusing for the original