When working with pixel art it is common to create a virtual screen size. For example if my sprites are 16x16 pixels and my game world is 256x256. I would want to scale the size up to fit my computer's screen size. If the art was not scaled it would look really tiny, on a 1920x1080 monitor.

This is where the concept of a virtual screen size comes into play. I can virtually limit my game to use a small screen size, and then scale that up to match the target window size. In raylib this is achieved using a RenderTexture2D.

Implementation

First off I like to define some constants.

#define V_SCREEN_WIDTH 256
#define V_SCREEN_HEIGHT 256
#define V_SCALE 2
#define SCREEN_WIDTH  V_SCREEN_WIDTH * V_SCALE
#define SCREEN_HEIGHT V_SCREEN_HEIGHT * V_SCALE

In the above code the prefix V_ refers to virtual. So I am setting my virtual screen size to 256x256 pixels and applying the V_SCALE to get the actual window size. In this instance 256 x 2 = 512.

When opening a window with raylib I will pass in the SCREEEN_WIDTH and SCREEN_HEIGHT constants to the InitWindow method like so.

InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Game Title");

This will open a correctly sized game window. I now want to create a RenderTexture2D. This is what the game will be drawn on. It will then itself be scaled and drawn onto the actual game window.

To create the RenderTexture2D I use the following code.

const RenderTexture2D renderTexture = LoadRenderTexture(V_SCREEN_WIDTH, V_SCREEN_HEIGHT);
const Rectangle renderTextureSrc = (Rectangle){ 0.0f, 0.0f, V_SCREEN_WIDTH, -V_SCREEN_HEIGHT };
const Rectangle renderTextureDest = (Rectangle){ 0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT };
const Vector2 renderTextureOrig = {0};

// remember to unload the texture when finished using it
UnloadRenderTexture(renderTexture);
Notice that the renderTextureSrc rectangle uses a negative value for it's height. This is to prevent the texture from being drawn on upside down. The reasoning is helpfully explained in the raylib docs.

The render texture can then be drawn on to by creating a new texture mode.

BeginTextureMode(renderTexture);
    ClearBackground(BG_COLOR);
    DrawTextureRec(spritesheet, playerFrame, playerPos, WHITE);
EndTextureMode();

After this code is run the RenderTexture2D's texture is then drawn on to the main draw context at the correct scale.

BeginDrawing();
    ClearBackground(BG_COLOR);
    DrawTexturePro(renderTexture.texture, renderTextureSrc, renderTextureDest, renderTextureOrig, 0, WHITE);
EndDrawing();

This results in the small 16x16 pixel art being drawn at the correct scale, without loss of fidelity.