ScaleNx - Artifact Removal and Algorithm Improvement

Oh, shit! Those straight lines instead of stairsteps on the SMW logo…! :open_mouth:

The numbers from the Shantae HUD look very clean, too. Great job, dude.

thanks for the positive feedback you two!

no, not quite. to have a common base, the basic idea is that edge interpolation at scale factor 3 can be done by counting the pixels of a stair. the result is the number of subpixels we “shave” off. to make the transition a little bit smoother I’ll take one extra subpixel off after a staircase ends. here is a demonstration of level 1 to 3. red pixels are removed, blue pixels are added (of course from the pov of the shader this is the same just looked upside down):

to explain the rules… in pass2 the algorithm tags corner pixels, it also provides a basic edge rule I then use in pass3 for the level detection. to make it easy let’s assume we are looking at a horizontal staircase pattern and the subpixel in focus is the upper left one. so level 1 is trivial, it just checks if the subpixel is marked. for level2 we check if the edge beginning on the upper left goes on to the next pixel on the right and if one pixel below our position begins a new stair. for every additonal level we check if the edge goes on for one more pixel on each stair. and another demonstration for the first three levels. red marks the part of the upper stair, blue the part of the lower stair which must both be present to qualify the level:

in the SF3 character select screen examples with the digitized artworks it does an inferior job in comparison to the hybrid version. but I can see what you mean. even if used with rAA anti-aliased edges are a little bit rough. I’ll definitely gonna have a look at your super-xbr shader. but first I need some time to rank up in SF5!

Oh, great!

To help you understand how you can modify Super-xBR to introduce ScaleNX ideas, read this small text I wrote past year:

https://drive.google.com/file/d/0B_yrhrCRtu8GYkxreElSaktxS3M/view

It explains the main idea of it.

interesting paper. this helps a lot to understand the concept. I think the approach or scalefx would need to undergo some big changes though to make it work. what I see as the main difference between the two shaders is that xbr looks at the grand scheme while scalefx acts very locally. currently my shader doesn’t use something like edge strength to determine how to interpolate.

one of the core elments in scalefx is to avoid artefacts (occuring in the original filter) by resolving disambigous setups at pixel junctions. this is done by taking only the subpixels in consideration which are lying directly at the junction in question. so in other words, in this part of the algorithm I only look at 4 pixels to determine if there is a NW-SE or NE-SW edge (or neither) going through a junction. this is why scalefx honors little details so much which is great for true pixelart. which angle is present is then indirectly calculated by the ruleset for edge levels I explained above. so the only part where strength values are compared is in the dissolve junction formula (pass2) and these are based on 2 pixel long 45° diagonals.

also scalefx is working on scale factor 3 where the original pixel color is kept in the center subpixel and not the upper left one. not saying that it can’t work, but it’ll probably need a lot of modifications on both sides.

[QUOTE=Sp00kyFox;34670]interesting paper. this helps a lot to understand the concept. I think the approach or scalefx would need to undergo some big changes though to make it work. what I see as the main difference between the two shaders is that xbr looks at the grand scheme while scalefx acts very locally. currently my shader doesn’t use something like edge strength to determine how to interpolate.

one of the core elments in scalefx is to avoid artefacts (occuring in the original filter) by resolving disambigous setups at pixel junctions. this is done by taking only the subpixels in consideration which are lying directly at the junction in question. so in other words, in this part of the algorithm I only look at 4 pixels to determine if there is a NW-SE or NE-SW edge (or neither) going through a junction. this is why scalefx honors little details so much which is great for true pixelart. which angle is present is then indirectly calculated by the ruleset for edge levels I explained above. so the only part where strength values are compared is in the dissolve junction formula (pass2) and these are based on 2 pixel long 45° diagonals.

also scalefx is working on scale factor 3 where the original pixel color is kept in the center subpixel and not the upper left one. not saying that it can’t work, but it’ll probably need a lot of modifications on both sides.[/QUOTE]

Have you thought about using xbr-noblend as a first pass at 3x and the next passes using ScaleNx?

no, not really. I’ll keep it in mind if I’m coming back for this shader.

tl;dr: improved edge transition and performance.

download: https://mega.nz/#!bU4AUA7C!3VjlM64gKG1GGd2lrfImisdvujST3DR5wmG1TSjZEQs

small update. after my explanations in the previous posts I rethought the transition of edges into straight lines. the extra subpixel on level 1 edges is fine but not enough for edges with other levels. if we think about it as linear function graphs with a certain slope then an edge with level N has the slope of 1/N and a straight horizontal line has a slope of 0 of course. so the transition should meet in between those two which gives us (1/N+0)/2 =1/(2N) which corresponds to an edge with level 2N. so we “shave off” 2 subpixels at the last stair for a level1 edge, 4 subpixels for level2, 6 subpixels for level3 and so on and so forth.

it’s not a huge difference in general but I verified in tests that it does give a better result. on top of that the positive side effect is that the amount of texture lookups in pass3 could be greatly reduced again from 21 to 13. for performance testing I usually see how it runs with the bsnes accuracy core when applied twice for a scale factor of 9. for the first time it runs in fullspeed for me without struggling. would be interesting to know if this shader also works well on consoles or handhelds after the performance improvements of the last updates.

I just updated the repo with this new version. Thanks, Sp00kyFox.

I have taken a look at your shaders and found the color difference code very interesting. I’ve read the source page and got the original formulas to test on my xbr shaders. And I find the results better than just using the luma values as I was doing. The only problem is that it’s very expensive, so I think I’ll only insert it in the multipass versions. It basically get rid of the stray red spike artifacts of current xbr, which I knew were caused by an inaccurate color diff function.

nice! as I was starting with the development I tested several fast methods for color metrics but this one was surely the best. yeah it costs more but still more performant than going the full way and doing a Lab-colorspace conversion. feel free to use my implementation for it. it just looks a litte convoluted since I implemented it in a way so it does 4 metric calculations at once but I didn’t changed the formula itself apart from inversing the result and scaling it to [0,1]. you can also get rid of the square root by squaring your threshold value which you only need to do once if it is constant. I coudn’t do it in my case since I needed to use the metric result as the output of a shader pass and without the square root there is a noticeable precision loss due to the frame buffer. here is the “clean” float4-version if you have a use for it:

float4 df(float4x3 A, float4x3 B)
{
	float4x3 diff = A-B;
	float4   ravg = 0.5 * (A._m00_m10_m20_m30 + B._m00_m10_m20_m30);

	diff *= diff * transpose(float3x4(2.0 + ravg, float4(4), 3.0 - ravg));
	
	return mul(diff, float3(1));
}

the result of df(A,B) is the squared difference of (A.x, B.x), (A.y, B.y), (A.z, B.z) and (A.w, B.w). maybe you have another idea to speed it up?

a little teaser…

It’s looking great! I can see that you’re taking the same path xbr took. I can see some anti-aliasing filtered.

You can improve some glitches by changing the color distance params. Try those values I posted earlier and you’ll see some fixes (Yoshi’s eyebrows and nose for example).

I really like how it handles gradual curves. That dolphin from SMW looks beautiful.

Here’s another image test I use when trying new ideas (maybe it’s useful for you):

Copy directly from this link (do not copy from the resized image above): http://abload.de/img/my_test2pios9.png

actually the issue I was trying to fix was zig-zag lines, like the mouth from the ghost in SMW which weren’t interpolated at all in prior versions. so I made the requirement for corner candidates less strict which also had a positive effect on the handling of anti-aliased edges. I should mention that the filter doesn’t mix colors. I don’t have the intention to make the filter go in the same direction as xBR and compete with it. I want ScaleFX to be a interpolation filter specialized in pixelart with decision making based on a very local neighborhood. like in the tradition of classic filters but expanded to a level which wasn’t possible back then.

despite the latest changes your triplets are still not a good choice for this filter. the original one seems to be the most balanced for ScaleFX.

thanks and I appreciate it that you presented my filter on your blog!

here it is:

I was trying around with some shader combinations and I found out that xsoft is a pretty good complementary filter if you want a smoother picture.

original

ScaleFX + xsoft

and here is one from the game Blackwell Epiphany (btw an awesome adventure series). too bad it’s just a screenshot, we seriously need a libretro dx hook!

original

ScaleFX-hybrid + xsoft

It’s looking great. That example shows a very good output from the filter.

Dear God… it’s beautiful. These are both just in the Shaders_CG folder right. (is glsl better?) This is going to be my new “HDMI” preset.

@SkyHighGam3r thanks! not yet. it was just a preview for the upcoming version but I’m still working on it. don’t wanna release another version which is outdated by a new update after a few days. you can still use the current version though. you can find it under shaders_cg/scalenx/scalefx-3x.cgp. if you wanna combine it with xsoft like in the screenshot you need to load shaders_cg\xsoft\shaders\4xsoft.cg on top of it (nearest, 2x but 1x works as well).

the wait is over. I finished my filter so far and it’s available on the shader repository (you can get it by using the “Download Zip” button on the main page). from now on ScaleFX can be found under the main folder scalefx:

here are the noteworthy changes:

  • reduced the number of passes to 4 (all metric work is now done in the first pass) -> better performance
  • improved edge rules -> more anti-aliased edges are interpolated
  • fixed: sometimes little bumps would appear on edges if an interpolation was tangent to it
  • improved performance in the final pass by removing a lot of unnecessary switch-case structures

and here are some examples. in the case of SF3 and the Wadjet Eye adventure games I used ScaleFX-hybrid:

http://screenshotcomparison.com/comparison/167831 http://screenshotcomparison.com/comparison/167832 http://screenshotcomparison.com/comparison/167833 http://screenshotcomparison.com/comparison/167840

(ps: hardcoregaming101.net is a great source of unaltered pixelart screenshots with original resolution)

I hope you enjoy it!

It looks great! The slopes in level 6 are very good!

Maybe there’s some way to blur a bit less than xSoft, to make it a bit more crispy. IMO, I think that xSoft damage the colors too much.

Wow, this looks freakin awesome. Not my personal tastes in a shader being more of a CRT guy but damn this looks really good for anyone who prefers the whole “smooth look” type of shader.