I'm starting with SDL2 and having some trouble trying to understand what an SDL_Renderer is.
What is it? What does it do? What's the difference between SDL_Renderer, SDL_Window, SDL_Surface and SDL_Texture and how they are related?
I had issues with this when trying to understand this introductory code:
#include <iostream>
#include <SDL2/SDL.h>
int main()
{
/* Starting SDL */
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
/* Create a Window */
SDL_Window *window = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (window == nullptr) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
return 1;
}
/* Create a Render */
SDL_Renderer *render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (render == nullptr) {
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
return 1;
}
/* Load bitmap image */
SDL_Surface *bmp = SDL_LoadBMP("./Tutorial/res/Lesson1/hello.bmp");
if (bmp == nullptr) {
std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
return 1;
}
/* Upload surface to render, and then, free the surface */
SDL_Texture *texture = SDL_CreateTextureFromSurface(render, bmp);
SDL_FreeSurface(bmp);
if (texture == nullptr){
std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
return 1;
}
/* Draw the render on window */
SDL_RenderClear(render); // Fill render with color
SDL_RenderCopy(render, texture, NULL, NULL); // Copy the texture into render
SDL_RenderPresent(render); // Show render on window
/* Wait 2 seconds */
SDL_Delay(5000);
/* Free all objects*/
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(render);
SDL_DestroyWindow(window);
/* Quit program */
SDL_Quit();
return 0;
}
I was using Twinklebear tutorial (suggested on SDL Wiki) and looked also on SDL Wiki Documentation and some books. But all of them assume that I know these definitions.
SDL_Window
is the struct that holds all info about the Window itself: size, position, full screen, borders etc.
SDL_Renderer
is a struct that handles all rendering. It is tied to a SDL_Window
so it can only render within that SDL_Window
. It also keeps track the settings related to the rendering. There are several important functions tied to the SDL_Renderer
SDL_SetRenderDrawColor(renderer, r, g, b, a);
This sets the color you clear the screen to ( see below )
SDL_RenderClear(renderer);
This clears the rendering target with the draw color set above
SDL_RenderCopy(
This is probably the function you'll be using the most, it's used for rendering a SDL_Texture
and has the following parameters :
SDL_Renderer* renderer,
SDL_Texture* texture,
const SDL_Rect* srcrect,
The part of the texture you want to render, NULL if you want to render the entire texture const SDL_Rect* dstrect)
SDL_Rect
is smaller or larger than the dimensions of the texture itself, the texture will be stretched according to this SDL_Rect
SDL_RenderPresent(renderer);
The SDL_Renderer
renders SDL_Texture
, which stores the pixel information of one element. It's the new version of SDL_Surface
which is much the same. The difference is mostly that SDL_Surface
is just a struct
containing pixel information, while SDL_Texture
is an efficient, driver-specific representation of pixel data.
You can convert an SDL_Surface* to SDL_Texture using
SDL_Texture* SDL_CreateTextureFromSurface(SDL_Renderer* renderer,
SDL_Surface* surface)
After this, the SDL_Surface should be freed using
SDL_FreeSurface( SDL_Surface* surface )
Another important difference is that SDL_Surface
uses software rendering (via CPU) while SDL_Texture
uses hardware rendering (via GPU).
The simplest struct in SDL. It contains only four shorts. x, y
which holds the position and w, h
which holds width and height.
It's important to note that 0, 0
is the upper-left corner in SDL. So a higher y
-value means lower, and the bottom-right corner will have the coordinate x + w, y + h
You can read more about SDL2 on my blog.