Handling high DPI (HiDPI) displays in SDL2 is crucial for ensuring your game looks crisp on modern screens. SDL2 provides built-in support for HiDPI, but you need to set it up correctly. Here's a comprehensive approach:
First, enable HiDPI support when creating your window:
#include <SDL.h>
#include <iostream>
int main() {
SDL_Init(SDL_INIT_VIDEO);
// Enable HiDPI support
SDL_SetHint(
SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
SDL_Window* window = SDL_CreateWindow(
"HiDPI Game", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 800, 600,
SDL_WINDOW_ALLOW_HIGHDPI |
SDL_WINDOW_RESIZABLE);
if (!window) {
std::cout << "Failed to create window: " <<
SDL_GetError() << "\n";
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(
window, -1,
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
if (!renderer) {
std::cout << "Failed to create renderer: "
<< SDL_GetError() << "\n";
return 1;
}
// Rest of the code...
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
The window size reported by SDL might not match the actual pixel size on HiDPI displays. Use SDL_GetRendererOutputSize()
to get the true pixel size:
int windowWidth, windowHeight,
renderWidth, renderHeight;
SDL_GetWindowSize(
window, &windowWidth, &windowHeight);
SDL_GetRendererOutputSize(
renderer, &renderWidth, &renderHeight);
float scaleX = renderWidth
/ static_cast<float>(windowWidth);
float scaleY = renderHeight
/ static_cast<float>(windowHeight);
std::cout << "Window size: " << windowWidth
<< "x" << windowHeight << "\n";
std::cout << "Render size: " << renderWidth
<< "x" << renderHeight << "\n";
std::cout << "Scale factor: " << scaleX
<< "x" << scaleY << "\n";
Use the scale factor when rendering:
SDL_Rect GetScaledRect(int x, int y, int w,
int h, float scaleX,
float scaleY) {
return SDL_Rect{
static_cast<int>(x * scaleX),
static_cast<int>(y * scaleY),
static_cast<int>(w * scaleX),
static_cast<int>(h * scaleY)};
}
// In your render loop:
SDL_Rect rect = GetScaledRect(
100, 100, 200, 200, scaleX, scaleY);
SDL_RenderFillRect(renderer, &rect);
Mouse input coordinates are already adjusted by SDL2, but you might need to scale other input values:
int mouseX, mouseY;
SDL_GetMouseState(&mouseX, &mouseY);
float gameX = mouseX / scaleX;
float gameY = mouseY / scaleY;
For the best visual quality, provide high-resolution versions of your assets and scale them down as needed:
SDL_Surface* LoadScaledSurface(
const char* path, float scale) {
SDL_Surface* original = SDL_LoadBMP(path);
if (!original) return nullptr;
int newWidth = static_cast<int>(original->w *
scale);
int newHeight = static_cast<int>(original->h *
scale);
SDL_Surface* scaled =
SDL_CreateRGBSurface(0, newWidth, newHeight,
32, 0, 0, 0, 0);
SDL_BlitScaled(original, nullptr, scaled,
nullptr);
SDL_FreeSurface(original);
return scaled;
}
By following these steps, your SDL2 game will look great on both standard and HiDPI displays, providing a consistent experience across different screen resolutions.
Answers to questions are automatically generated and may not have been reviewed.
Learn techniques for scaling images and working with aspect ratios