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! :)