-
-
Notifications
You must be signed in to change notification settings - Fork 138
Add several scaling modes for non-integer upscaling #425
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
Conversation
|
Hi! No real concerns about the code or code quality, but I am going to be critical of some of the features in this. Simple bilinear filtering is (IMHO) not on the table. It looks terrible when the scaling factor is too large (it's hard to say what "too large" is quantitatively). The non-aspect-preserving stretch also goes against the grain here. I'm not really interested in supporting these use cases, even if they are trivial, due to output quality concerns. The last mode (hybrid) is interesting, but reminds me of an antialiasing algorithm. I can't quite see the use case for this one (but see my notes below that compares it to an alternative). The pixel grid in However, it does remind me of something that I implemented in the precursor to Taking the same idea one step further, rather than scaling only horizontally to compensate for the pixel aspect ratio, the second pass could scale in both directions to fill the screen. This will also result in minimal blurring. (Except in degenerate cases where the nearest pass uses a 1x scale factor.) The two-pass scaling also generalizes to a single-pass fragment shader, which is very close to the hybrid shader (the main difference I can see is that the I started a draft PR long ago in an effort to implement pixel aspect ratio support using the former method described in my blog post: #151. This thread contains more context, and it can be used as a point of comparison (but maybe not much more than that: it's based on a very outdated revision). Anyway, I would love to support a "fill the screen, I don't care if it's exactly pixel perfect" scaling mode, but I absolutely want to preserve crispness in the output as much as possible. At least in the main crate, which strives to do the right thing with low effort on the user's part. |
|
Well the use case for the "hybrid" scaling is that it's comparable to an integer upscale followed by a linear upscale. I am not aware of a better solution to fit a pixel buffer to the window, in a non-integer ratio, while preserving the sharp borders between input pixels. Implementing it as a single pass is more efficient and avoids having to allocate a temporary texture, and it avoids having to complicate the current code. As a pixels user for a software rasterizer I have no upscaling preference and would have been content with a straightforward linear upscale for my usecase. I was just looking for a solution to fit to the window. But I respect if you want to only support certain approaches. |
|
I could just call the Hybrid mode |
|
You're right, that was a bug. I believe I have fixed it. At least from what I can see integer ratios scale cleanly now, while preserving one pixel of interpolation for non-integer scales. I could not reproduce the two pixels of interpolation by the way. Perhaps it is fixed now (as this change in the shader makes more sense to me) but please check on your end. |
|
Thank you! It is looking really solid, now. I think it is behaving almost exactly as I expected. There will probably be more lints to resolve. |
|
For the too many arguments lint, I think it makes sense to create intermediate structs to replace multiple args. Most of the WGPU types can be combined into one struct, for instance. The other option is ignoring the lint ( |
|
I'm just going to add |
|
Alright, I'll merge this and maybe follow up with some additional PRs later. Thank you! |








This PR adds a new
ScalingModeenum and aset_scaling_modefunction. The scaling mode defaults toScalingMode::PixelPerfectwhich preserves the current integer upscaling code.ScalingMode::LinearPreserveAspectis a simple bilinear upscale which preserves the input buffer aspect ratio.ScalingMode::LinearStretchis a simple bilinear upscale which does not preserve aspect ratio.ScalingMode::PixelPerfectHybridis the most interesting one. It's basically a single pass "integer+linear" upscaling approaching using custom bilinear filtering weights. It preserves the input buffer aspect ratio. It was inspired by https://csantosbh.wordpress.com/2014/01/25/manual-texture-filtering-for-pixelated-games-in-webgl/The names for the enum fields were just a quick guess on my part. "PixelPerfectHybrid" is maybe not the best naming choice as it's not 100% pixel perfect.