Customising Mouse Cursors

Preventing Cursor Blur When Scaling

Why does my custom cursor look blurry/pixelated when I scale my window? How can I make it stay sharp?

Abstract art representing computer programming

When working with custom cursors in SDL2, maintaining cursor sharpness during window scaling involves several considerations and potential solutions.

Understanding the Problem

Custom cursors can become blurry for two main reasons:

  • Window scaling causing pixel interpolation
  • Using cursor images at the wrong resolution for your display

Solution 1: Multi-Resolution Cursors

Create a system that loads different cursor sizes based on the window scale:

#include <SDL.h>
#include <SDL_image.h>
#include <unordered_map>
#include <string>

class ScalableCursor {
public:
  struct CursorSize {
    int width;
    int height;
    SDL_Cursor* cursor;
  };

  ScalableCursor() {
    // Load cursor variants
    LoadCursorVariant("cursor_16.png", 16, 16);
    LoadCursorVariant("cursor_32.png", 32, 32);
    LoadCursorVariant("cursor_64.png", 64, 64);
  }

  void UpdateForScale(float windowScale) {
    // Choose best cursor size for current scale
    int targetSize = static_cast<int>(16.0f * windowScale);

    SDL_Cursor* bestCursor{nullptr};
    int smallestDiff{INT_MAX};

    for (const auto& [size, cursorInfo] : Cursors) {
      int diff{std::abs(size - targetSize)};
      if (diff < smallestDiff) {
        smallestDiff = diff;
        bestCursor = cursorInfo.cursor;
      }
    }

    if (bestCursor) {
      SDL_SetCursor(bestCursor);
    }
  }

private:
  void LoadCursorVariant(
    const std::string& path,
    int width,
    int height
  ) {
    SDL_Surface* surface{IMG_Load(path.c_str())};
    if (!surface) {
      return;
    }

    SDL_Cursor* cursor{SDL_CreateColorCursor(
      surface, width/2, height/2)};
    SDL_FreeSurface(surface);

    if (cursor) {
      Cursors[width] = {width, height, cursor};
    }
  }

  std::unordered_map<int, CursorSize> Cursors;
};

Solution 2: Custom Rendering with Pixel-Perfect Scaling

If you're using custom cursor rendering, maintain pixel-perfect scaling:

class PixelPerfectCursor {
public:
  void Render(
    SDL_Renderer* renderer,
    int mouseX,
    int mouseY,
    float scale
  ) {
    // Calculate pixel-aligned position
    int alignedX{static_cast<int>(
      std::round(mouseX / scale) * scale)};
    int alignedY{static_cast<int>(
      std::round(mouseY / scale) * scale)};

    // Set nearest-neighbor scaling
    SDL_SetHint(
      SDL_HINT_RENDER_SCALE_QUALITY, "0");

    SDL_Rect destRect{
      alignedX,
      alignedY,
      static_cast<int>(CursorWidth * scale),
      static_cast<int>(CursorHeight * scale)
    };

    SDL_RenderCopy(
      renderer,
      CursorTexture,
      nullptr,
      &destRect
    );
  }

private:
  SDL_Texture* CursorTexture;
  int CursorWidth{16};
  int CursorHeight{16};
};

Both solutions help maintain cursor sharpness during scaling. The first approach is better for traditional cursor implementation, while the second works well with custom rendering.

Remember to create your cursor images with clean, pixel-art style edges for best results when scaling.

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 79 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2025 - All Rights Reserved