Dink HD - Good Shadows Patch
Dink Smallwood HD
One thing that's annoyed me about Dink for about 19 years is the checkerboard shadow pattern.
When shadows overlap, it results in 'flickering' shadows where an entire region is either black or checkerboard:
DinkHD has support for Pic Smoothing, which is nice, but there is still a faint checkboard pattern depending on where the pixel rounding (?) occurs, and it makes everything else blurry:
I thought there was a better way. So, I made a small patch to the DinkHD source code to detect the checkboard shadow pattern, and when it is detected, convert it to a nice anti-aliased alpha-channel shadow.
(These screenshots are with Pic Smoothing = Off!)
It does end up converting all SURFACE_PALETTE_8BIT textures to SURFACE_RGBA, even those without shadows. It could probably be optimized / improved.
Apply this patch to svn://rtsoft.com/rtsvn/proton/shared/Renderer ; rev 1477
Does this seem interesting to anyone else?
When shadows overlap, it results in 'flickering' shadows where an entire region is either black or checkerboard:
DinkHD has support for Pic Smoothing, which is nice, but there is still a faint checkboard pattern depending on where the pixel rounding (?) occurs, and it makes everything else blurry:
I thought there was a better way. So, I made a small patch to the DinkHD source code to detect the checkboard shadow pattern, and when it is detected, convert it to a nice anti-aliased alpha-channel shadow.
(These screenshots are with Pic Smoothing = Off!)
It does end up converting all SURFACE_PALETTE_8BIT textures to SURFACE_RGBA, even those without shadows. It could probably be optimized / improved.
Apply this patch to svn://rtsoft.com/rtsvn/proton/shared/Renderer ; rev 1477
Does this seem interesting to anyone else?
Woah, that's awesome!
I'll see if I can safely apply the patch for the next beta release!
Also: For legal reasons (Ubisoft and a few other companies use Proton SDK so I have to be very careful) can you make it clear that you wrote this code, and are donating this code to Proton SDK free of charge, royalties, etc so it is compatible with the Proton SDK license? If you say that in a reply here, I'll just link that reply directly from your modified/added function(s). Hopefully wayback machine will grab it for the future as well.
I'll make a few changes so this can be optionally run as slow mobile devices may not be able to handle this change. (also, default functionality of proton can't be changed)
PS: Why the change to glColorBytes::Compare? I would have thought my version was quicker (single 32 bit compare vs 4 byte compares). Did you profile this change under release mode?
I'll see if I can safely apply the patch for the next beta release!
Also: For legal reasons (Ubisoft and a few other companies use Proton SDK so I have to be very careful) can you make it clear that you wrote this code, and are donating this code to Proton SDK free of charge, royalties, etc so it is compatible with the Proton SDK license? If you say that in a reply here, I'll just link that reply directly from your modified/added function(s). Hopefully wayback machine will grab it for the future as well.
I'll make a few changes so this can be optionally run as slow mobile devices may not be able to handle this change. (also, default functionality of proton can't be changed)
PS: Why the change to glColorBytes::Compare? I would have thought my version was quicker (single 32 bit compare vs 4 byte compares). Did you profile this change under release mode?
Does this work if the shadow isn't specifically black? IIRC, there are some really dark grey shadows in some DMODS so that they can use full white (Like in Pilgrims Quest), as well as being used to make light in others (I don't remember which one(s) do this...).
One thing that's annoyed me about Dink for about 19 years is the checkerboard shadow pattern.
When shadows overlap, it results in 'flickering' shadows where an entire region is either black or checkerboard:
That's dithering for you. It's to make an illusion that something is transparent by removing each pixel either in odd or even number to make that. But this is an awesome job man.
Changing color for entire screen or sprite via script when?
When shadows overlap, it results in 'flickering' shadows where an entire region is either black or checkerboard:
That's dithering for you. It's to make an illusion that something is transparent by removing each pixel either in odd or even number to make that. But this is an awesome job man.
Changing color for entire screen or sprite via script when?
Yes, I wrote the code, and am donating this to Proton SDK free of charge. I'm releasing it under the CC0 license; if anyone wants it, feel free to use it.
As for "why the change to glColorBytes::Compare": I was very tired, and I was trying to get the dumb thing to work I had some mistakes in my code, misread your existing compare function (I thought it was just comparing the red channel, but if that was the case, none of it would actually work).
I'm happy that you saw (and fixed) the 'black house shadow' issue. I might try to tweak this a little bit to work with more than just pure-black checkboard patterns.
As for "why the change to glColorBytes::Compare": I was very tired, and I was trying to get the dumb thing to work I had some mistakes in my code, misread your existing compare function (I thought it was just comparing the red channel, but if that was the case, none of it would actually work).
I'm happy that you saw (and fixed) the 'black house shadow' issue. I might try to tweak this a little bit to work with more than just pure-black checkboard patterns.
Dan - thanks! I've committed all changes to both proton and Dink. By default it's enabled for Windows builds but can be turned off if needed in the options. Might be ok for mobile too, will do performance testing later after the improvements/bugfixes are done.
Man! I couldn't stop laughing when I saw this. I'm constantly getting amazed by the energy, willingness and knowledge of some people. Nice job
This is cool and all, but isn't it treating the symptom instead of the sickness? If you could expand the sourse to import additional image formats that support an alpha channel (tga or png?) you could instead run a script similar to this to batch convert all images before importing them, I assume this would give better performance and open up a lot mire freedom for people making art for their dmods with half the inclusion of semi-transparency!
I respectfully disagree; while I agree that true alpha-channel support would be nice, I think that having the Dink engine convert from checkerbox to alpha shadows directly is better than converting all existing graphics to use alpha shadows for a couple reasons:
1) As currently implemented, this works with all existing D-Mods without needing to change them (which would greatly increase the download size and file size of all graphics).
2) Right now this can be enabled/disabled from the Dink HD options menu, as it may have a performance cost associated with it.
And... actually... with what I learned updating the checkerboard code, I'm pretty sure Dink supports alpha channel already.
[5 Minutes Later]
Yep!
Apparently Photoshop is the issue; it can't write .bmp with alpha channel, but PixelFormer can (https://stackoverflow.com/a/34572996). So you can use Photoshop to create transparent .pngs, and use PixelFormer to convert those to transparent .bmps.
I tried converting the Initiation lantern to alpha channel, and it works (and plays nice with the 'good shadows' too):
I might play around with this more.
It even 'kind-of' works in FreeDink; it has some unintentional flickering issues, where if the size of the lantern sprite is 100%, it is solid black, but if the size of the sprite is something like 105% or 110%, then it is solid black every-other-frame or so (and literally flickers on-and-off).
Doesn't work at all in v1.08.
1) As currently implemented, this works with all existing D-Mods without needing to change them (which would greatly increase the download size and file size of all graphics).
2) Right now this can be enabled/disabled from the Dink HD options menu, as it may have a performance cost associated with it.
And... actually... with what I learned updating the checkerboard code, I'm pretty sure Dink supports alpha channel already.
[5 Minutes Later]
Yep!
Apparently Photoshop is the issue; it can't write .bmp with alpha channel, but PixelFormer can (https://stackoverflow.com/a/34572996). So you can use Photoshop to create transparent .pngs, and use PixelFormer to convert those to transparent .bmps.
I tried converting the Initiation lantern to alpha channel, and it works (and plays nice with the 'good shadows' too):
I might play around with this more.
It even 'kind-of' works in FreeDink; it has some unintentional flickering issues, where if the size of the lantern sprite is 100%, it is solid black, but if the size of the sprite is something like 105% or 110%, then it is solid black every-other-frame or so (and literally flickers on-and-off).
Doesn't work at all in v1.08.
THAT SMOOTH SHADOW MADE ME CREAM.
not really though.
not really though.
Fair enough! I guess compability with D-Mods greatly outweigh the drawbacks of performance costs!
Wow, that is very exciting to learn Dink HD supports BMPs with alpha. This is reason enough to make a Dink HD exclusive D-Mod in my book!
Now that you have been looking a bit closer at the graphics pipeline, do you have any idea how hard it would be to expose blending properties of sprites in dinkC? It would be so cool if you could set fireballs or fireplaces to additive blending so they brighten the pixels behind them instead of replacing them. This should already be a function in openGL, so I assume it would be as simple as adding a property on the sprite objects? Is the problem that it would break compatibility with other dmods if things like that would be added?
Wow, that is very exciting to learn Dink HD supports BMPs with alpha. This is reason enough to make a Dink HD exclusive D-Mod in my book!
Now that you have been looking a bit closer at the graphics pipeline, do you have any idea how hard it would be to expose blending properties of sprites in dinkC? It would be so cool if you could set fireballs or fireplaces to additive blending so they brighten the pixels behind them instead of replacing them. This should already be a function in openGL, so I assume it would be as simple as adding a property on the sprite objects? Is the problem that it would break compatibility with other dmods if things like that would be added?
I'd still go with the PNG. Specially when it can compress the file size without losing any quality.
and performance problems? I may not be a programmer but i don't think there would be any.
EDIT: There's also TIFF images, these also have a alpha channel.
and performance problems? I may not be a programmer but i don't think there would be any.
EDIT: There's also TIFF images, these also have a alpha channel.
Yeah, .png support would be good. Maybe the engine should always check for .png before .bmp versions, that way you can replace original files very easily without changing script files or anything.
Sprite blending modes would be possible... everything would have to be set up again when loading a normal save (not a big problem, all scripts are reloaded anyway in that case, so they could do the sp_set_blending_mode() or whatever at init), but the full save states could remember the active settings.
Sprite blending modes would be possible... everything would have to be set up again when loading a normal save (not a big problem, all scripts are reloaded anyway in that case, so they could do the sp_set_blending_mode() or whatever at init), but the full save states could remember the active settings.
That would be great!
A command like sp_set_opacity(0-100) would also be great in conjunction to blending modes, then it would be easy to create flickering fires, "ghost"-effects and fading in and out sprites!
A command like sp_set_opacity(0-100) would also be great in conjunction to blending modes, then it would be easy to create flickering fires, "ghost"-effects and fading in and out sprites!
For anyone wondering how it looks with a checkerboard over the full screen
https://imgur.com/a/CLEhH
https://imgur.com/6L1hxmr (Make it double even.)
https://imgur.com/a/CLEhH
https://imgur.com/6L1hxmr (Make it double even.)
I created a new patch to fix a couple shadow issues.
even-better-shadows.patch, apply to svn://rtsoft.com/rtsvn/proton/shared/Renderer . CC0 licensed.
1) First patch resulted in all characters having 'spiky shoes' (solid black pixels at boundary between sprite and shadow). This has been reduced:
Before:
After:
2) First patch only worked if the checkboard pattern was black. Now it works with all colors.
Before:
After:
even-better-shadows.patch, apply to svn://rtsoft.com/rtsvn/proton/shared/Renderer . CC0 licensed.
1) First patch resulted in all characters having 'spiky shoes' (solid black pixels at boundary between sprite and shadow). This has been reduced:
Before:
After:
2) First patch only worked if the checkboard pattern was black. Now it works with all colors.
Before:
After:
Hey, Dan, what alpha value are there new shadows rendered at?
I'm going to update my dink shadows for blender startup file and I would like to give a switch where the user can render both classic checkerboard shadows and alpha shadows for for dink HD and I would like to match the alpha value of the generated alpha shadows as close as possible.
I'm going to update my dink shadows for blender startup file and I would like to give a switch where the user can render both classic checkerboard shadows and alpha shadows for for dink HD and I would like to match the alpha value of the generated alpha shadows as close as possible.
Each shadow pixel is 0,0,0,128.
If a transparent pixel touches a shadow pixel, it will be 0,0,0,32*N, where N is the number of shadow pixels that it touches. I don't think you can control that level of detail, but maybe?
If a transparent pixel touches a shadow pixel, it will be 0,0,0,32*N, where N is the number of shadow pixels that it touches. I don't think you can control that level of detail, but maybe?
Oh, the idea of the 32*N is to get an anti-aliasing effect where there is a fade from shadow to non-shadow? Yeah, I don't control it on that level, but I'll blur the edges slightly to match it
Somewhat related: to make iplaydink happy, I tried adding preliminary png support (palette pngs, 24-bit pngs, and alpha pngs). It works.
http://www.redrecondite.com/dinkhd/DinkPng.patch CC0 licensed.
It is really messy. My real job is pretty hectic right now, so I'm not sure if I'll have much time to clean up the implementation.
I've only really tested it with Debug GL configuration; it probably doesn't work in Release GL. I have no idea how/if this would work with mobile builds.
There is some sort of conflict with 'Pic Smoothing', where if a sprite is all alpha channel it will have a halo.
I also created a couple batch file that can convert any existing .bmp files to .png recursively (requires imagemagick to be installed):
pngify.bat
recurpngify.bat
Then just run recurpngify.bat, and everything will be converted to pngs. You could probably whip something up in Toolfish to do that easier.
All Dink graphics are around 33.0 MB in BMP format, and 8.17 MB in PNG format.
http://www.redrecondite.com/dinkhd/DinkPng.patch CC0 licensed.
It is really messy. My real job is pretty hectic right now, so I'm not sure if I'll have much time to clean up the implementation.
I've only really tested it with Debug GL configuration; it probably doesn't work in Release GL. I have no idea how/if this would work with mobile builds.
There is some sort of conflict with 'Pic Smoothing', where if a sprite is all alpha channel it will have a halo.
I also created a couple batch file that can convert any existing .bmp files to .png recursively (requires imagemagick to be installed):
pngify.bat
mogrify -format png *.bmp del /F *.bmp
recurpngify.bat
call "%~dp0pngify.bat" for /r /d %%x in (*) do ( pushd "%%x" call "%~dp0pngify.bat" popd )
Then just run recurpngify.bat, and everything will be converted to pngs. You could probably whip something up in Toolfish to do that easier.
All Dink graphics are around 33.0 MB in BMP format, and 8.17 MB in PNG format.
Cool!
I already have libpng in /Irrlicht/source/Irrlicht/libpng btw so shouldn't need the libpng files (the irrlicht-based demos use libpng, but I never added direct support for it in Surface/SoftSurface as .png's get changed to .rttex format and I didn't need to load .png files directly before now)
I'll see if I can fold this in
I already have libpng in /Irrlicht/source/Irrlicht/libpng btw so shouldn't need the libpng files (the irrlicht-based demos use libpng, but I never added direct support for it in Surface/SoftSurface as .png's get changed to .rttex format and I didn't need to load .png files directly before now)
I'll see if I can fold this in
Update - ok, I put it in and updated svn!
I made two changes:
- RT_PNG_SUPPORT must be defined, so by default libpng isn't needed by SoftSurface
- The .c files from /Irrlicht/source/Irrlicht/libpng were added to the project (there is no messing with libs, this makes things simpler for the multi-platform compiling, it's just more source files as far as the app is concerned)
- No library/source path changes required
Note: I don't really have a way to test the .png support as I want to avoid changing the dink .ff files ... hopefully someone will make a dmod or something we could use as a test
I made two changes:
- RT_PNG_SUPPORT must be defined, so by default libpng isn't needed by SoftSurface
- The .c files from /Irrlicht/source/Irrlicht/libpng were added to the project (there is no messing with libs, this makes things simpler for the multi-platform compiling, it's just more source files as far as the app is concerned)
- No library/source path changes required
Note: I don't really have a way to test the .png support as I want to avoid changing the dink .ff files ... hopefully someone will make a dmod or something we could use as a test
Aha, cool!
I created a D-Mod that converted all of the original Dink graphics to pngs (and made fancy rainbow translucent pigs) here:
http://www.redrecondite.com/dinkhd/pngfarmer.dmod
There are some issues (they appear both in my old debug build and my build of the latest revision out of svn).
1) Some pngs aren't being read correctly? Right outside of Dink's house there are some suspicious translucent grey squares.
2) I saw a debug assertion when walking into the pig farm once.
I created a D-Mod that converted all of the original Dink graphics to pngs (and made fancy rainbow translucent pigs) here:
http://www.redrecondite.com/dinkhd/pngfarmer.dmod
There are some issues (they appear both in my old debug build and my build of the latest revision out of svn).
1) Some pngs aren't being read correctly? Right outside of Dink's house there are some suspicious translucent grey squares.
2) I saw a debug assertion when walking into the pig farm once.
Cool - ok, the problem is the .png loader doesn't know how to properly read 2bit (middle piece of the dialog background.. it's PNG_COLOR_TYPE_GRAY, so it might be 1 bit actually) or 4bit (\graphics\lands\grass\grass-04.png) images. (your converter chooses 4 bit if it's 16 colors or less, probably)
So a fix would be to force 8 bit when doing your conversion to png and just ignore those formats, or fix the loader.
I committed a few small changes - png loader now respects the "checkboard fix" flag, and no longer crashes if a surface failed to load. (it will still assert in debug mode and look crazy though!)
So a fix would be to force 8 bit when doing your conversion to png and just ignore those formats, or fix the loader.
I committed a few small changes - png loader now respects the "checkboard fix" flag, and no longer crashes if a surface failed to load. (it will still assert in debug mode and look crazy though!)
Ahhh, I see. I found some nice 'convenience' methods that basically try to convert any image to RGB / RGBA to support any of the weird palette types. I was able to figure out 4-bit palettes, but 2-bit were giving me trouble. I also added support for grayscale pngs.
http://www.redrecondite.com/dinkhd/PngFix.patch CC0
There's still that weird issue that when Pic Smoothing is on, there is a very subtle outline around sprites that doesn't appear with BMPs. It's really odd. It's like OpenGL thinks that this surface is 'different', but it shouldn't be able to tell the difference between a surface that came from a png or a bmp. I feel like I missed setting a member variable.
http://www.redrecondite.com/dinkhd/PngFix.patch CC0
There's still that weird issue that when Pic Smoothing is on, there is a very subtle outline around sprites that doesn't appear with BMPs. It's really odd. It's like OpenGL thinks that this surface is 'different', but it shouldn't be able to tell the difference between a surface that came from a png or a bmp. I feel like I missed setting a member variable.
Cool, I applied the patch. I do see the outline difference .. huh. It's like when the antialiasing is enabled it hard stops around the alpha channel, I don't know why there is a difference. By default pic smoothing is off, so maybe not a big deal though.