3
\$\begingroup\$

I looked at this page that mentions the SDL2_gfx library for rescaling SDL_Surfaces without the image getting blurry: SDL zooming/upscaling without images becoming blurry?

I wanted to know if it was a good idea and if there was any way (instead of individually resizing each texture, all relationships of space, and fixing the proportions of the speed for each object) to take the tiny scene of little sprites and tiles and rescale it before the image blits on the screen.

If there's a more reasonable solution, someone tell me, but this seems to make the most sense to me.

Thanks for the help!

\$\endgroup\$

1 Answer 1

9
\$\begingroup\$

In SDL 2, you must set the scaling interpolation algorithm for the whole renderer, using

SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, Value);

where Value should be, in your case (pixel art) 0. 1 means linear interpolation, and 2 is anistropic (only supported if the app runs on D3D/Windows) (documentation)

As far as saying itself is concerned, you can do it when you copy a texture to the renderer by specifying a target rectangle larger/smaller than the source rectangle.

// let's say the texture is 16*16px
SDL_Rect dest = {.x = 0, .y = 0, .w = 32, .h = 32}; // Scale by 2 -> 32*32.
// If SDL_SetHint was called properly, it will scale without blurring.
SDL_RenderCopy(renderer, texture, nullptr, dest);

Other possibility, you could set the renderer's logical scale to a fixed value (SDL_RenderSetLogicalSize(renderer, width, height)) that's smaller than the window's size. SDL will scale the renderer to fit the window using the algorithm given in SDL_SetHint().

The way I go about it when making pixel art game is the one you were hinting at: work at 1x resolution (sprites are not upscaled), and scale everything at the end.

If you want to scale only certain bits (let's say, HUD layer), you could render everything to a texture, and then upscale that texture before rendering it to the screen. To do that, the target texture must be created with the right flag (SDL_TEXTUREACCESS_TARGET), and then the renderer must be set to draw on it:

SDL_Texture* target = SDL_CreateTexture(renderer, PIXEL_FORMAT, SDL_TEXTUREACCESS_TARGET, width, height);
SDL_SetRenderTarget(renderer, target);
SDL_RenderClear(renderer); // to make sure the texture is "clean"
//
// render everything you want here
SDL_SetRenderTarget(renderer, nullptr); // to switch the renderer back to the screen
// render your target texture here, after upscaling it if you want

Hope all that helps! :)

\$\endgroup\$
2
  • \$\begingroup\$ I'm sorry, I don't quite understand. "The way I go about it when making pixel art game is the one you were hinting at: work at 1x resolution (sprites are not upscaled), and scale everything at the end." That's exactly how I want to do it. Are you saying i need to use RenderSetLogicalSize and sdl_SetHint in order to do it? i tried, but i really don't understand how. \$\endgroup\$
    – Cuppasoup
    Commented Jun 29, 2015 at 22:44
  • \$\begingroup\$ basically, you would set the renderer size when the game launches with SDL_RenderSetLogicalScale(). Once this is done, you can just treat the window as being exactly of that size, and SDL will take care of upscaling the result if the window is bigger than the logical scale you set the renderer to be. SDL_SetHint is used to determine what kind of interpolation should be used by SDL when it upscales the renderer. You should use "nearest" (the documentation has a list of the exact option names). \$\endgroup\$
    – amyinorbit
    Commented Jun 30, 2015 at 2:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .