Screens, images, texture and sprites are rectangular, so this shape has a special importance to SDL3 and graphics programming in particular.
Rectangles: TSDL_FRect, PSDL_FRect and PPSDL_FRect
PPSDL_FRect = ^PSDL_FRect;
PSDL_FRect = ^TSDL_FRect;
TSDL_FRect = record
x: cfloat;
y: cfloat;
w: cfloat;
h: cfloat;
end;
TSDL_FRect describes a rectangle by four float point values (indicated by the F prefix). The variables x and y correspond to the x/y coordinates of the left upper corner of the rectangle, related to the origin 0/0 which is the left upper corner of, e.g. a texture, window,… The variable w is the width and h the height of the rectangle.
Often functions require an argument of PSDL_FRect type. This is the pointer counterpart to TSDL_FRect. And for convenience there is a double pointer PPSDL_FRect available, which in some cases may be needed.
Using Rectangles for Positioning and Scaling
The following code demonstrates the basic principle how to position and scale a texture simply by using rectangles in SDL3. It assumes you have the fpsdl.bmp image file available from the previous chapter about rendering a bitmap file. (If not, copy it from there.)
program SDL3_Rectangles;
uses SDL3;
var
sdlWindow1: PSDL_Window;
sdlRenderer: PSDL_Renderer;
sdlSurface1: PSDL_Surface;
sdlTexture1: PSDL_Texture;
sdlRectangle: TSDL_FRect;
begin
// initilization of video subsystem
if not SDL_Init(SDL_INIT_VIDEO) then
Halt;
// create window and renderer
if not SDL_CreateWindowAndRenderer('SDL3 Rectangles', 500, 500, 0, @sdlWindow1, @sdlRenderer) then
Halt;
// create surface from file
sdlSurface1 := SDL_LoadBMP('fpsdl.bmp');
if sdlSurface1 = nil then
Halt;
// create texture from surface
sdlTexture1 := SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface1);
if sdlTexture1 = nil then
Halt;
// set scaling mode
SDL_SetTextureScaleMode(sdlTexture1, SDL_SCALEMODE_NEAREST);
// prepare rectangle enclosing word "SDL" in fpsdl.bmp
sdlRectangle.x := 17;
sdlRectangle.y := 104;
sdlRectangle.w := 73;
sdlRectangle.h := 36;
// render "SDL"-part from the texture to the whole window
SDL_RenderTexture(sdlRenderer, sdlTexture1, @sdlRectangle, nil);
// render the whole texture into the rectangle dimensions
SDL_RenderTexture(sdlRenderer, sdlTexture1, nil, @sdlRectangle);
// render to window for 2 seconds
SDL_RenderPresent(sdlRenderer);
SDL_Delay(2000);
// clear memory
SDL_DestroyTexture(sdlTexture1);
SDL_DestroySurface(sdlSurface1);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow (sdlWindow1);
// quitting SDL3
SDL_Quit;
end.
We will get this as a result.


The result of the example program (500×500 px window). A part of the full image is stretched in the background while the full image is also squeezed into a small area.
For comparison, the original 200×200 px image (fpsdl.bmp) looks like this:

The dotted black part marks the rectangle we used in the code.
Let’s dissect the code.
var
sdlWindow1: PSDL_Window;
sdlRenderer: PSDL_Renderer;
sdlSurface1: PSDL_Surface;
sdlTexture1: PSDL_Texture;
sdlRectangle: TSDL_FRect;
In the var clause we declare the known variables for window, renderer, surface and a texture. Also we have a new variable of TSDL_FRect type.
// prepare rectangle enclosing word "SDL" in fpsdl.bmp
sdlRectangle.x := 17;
sdlRectangle.y := 104;
sdlRectangle.w := 73;
sdlRectangle.h := 36;
After initializing SDL3 and setting up the window, renderer and texture as known, the rectangle is getting some values. It just encloses the word “SDL” in the original image (see above, black dots).
Scaling in SDL3
Scaling Mode
Right before creating the surface and texture, there is this line in code.
// set scaling mode
SDL_SetTextureScaleMode(sdlTexture1, SDL_SCALEMODE_NEAREST);
The SDL_SetTextureScaleMode(texture, scale mode) function sets the render mode. Possible values are
- SDL_SCALEMODE_NEAREST
- nearest pixel sampling
- nearest pixel sampling
- SDL_SCALEMODE_LINEAR
- linear filtering
The difference can be seen in the following image.


Scaling modes
Positioning and Scaling SDL3 Textures by using Rectangles
// render "SDL"-part from the texture to the whole window
SDL_RenderTexture(sdlRenderer, sdlTexture1, @sdlRectangle, nil);
// render the whole texture into the rectangle dimensions
SDL_RenderTexture(sdlRenderer, sdlTexture1, nil, @sdlRectangle);
At this point happens the magic that leads to the resulting image. By the way, since the SDL_RenderTexture function requires the rectangle arguments to be of PSDL_Rect, we use the @-operator (pointer operator) here.
// render "SDL"-part from the texture to the whole window
SDL_RenderTexture(sdlRenderer, sdlTexture1, @sdlRectangle, nil);
This means, copy the area described by “sdlRectangle” from the source (“sdlTexture1” here) to the whole area (because of the nil value) of the destination, hence the whole window.
Since the window has a width and height of 500 px each, whereas the source rectangle has just a width of 73 px and a height of 36 px, SDL3 automatically scales the image to fit into the larger dimensions of the window.
A Texture Atlas (Spritesheet)
Instead of creating individual textures for every sprite in a game, often one texture atlas is used. A texture atlas is a large texture which contains all textures for the game. When composing a game scene, you just render all the needed textures from the texture atlas by using corresponding rectangles as just seen above. This method is fast and convenient.
Let’s get back to the code.
// render the whole texture into the rectangle dimensions
SDL_RenderTexture(sdlRenderer, sdlTexture1, nil, @sdlRectangle);
This means, copy the whole source texture (because of nil value) to the area described by “sdlRectangle”. The source is the 200×200 px “Free Pascal meets SDL” texture, which is squeezed to the 73×36 px rectangle at (x/y)-position (17/104). This is just what you see in the resulting image (above) where the whole image is squeezed into this tiny area.
Movement of Textures (Sprites)
Although not covered directly by this code example, you get the picture how to achieve the impression of movement of textures (sprites). Every game loop cycle you adjust the (x/y) coordinates of the rectangle for the destination to bring the texture about to move.
Clean up
After rendering the two textures as seen above, the program is delayed for 2 seconds, then cleans all objects from memory and quits SDL3. Nothing new here, though.
Previous Chapter | Next Chapter
[Title image created with https://flatai.org; public domain]