First Commit

This commit is contained in:
2025-11-18 14:18:26 -07:00
parent 33eb6e3707
commit 27277ec342
6106 changed files with 3571167 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
This example code creates an SDL window and renderer, and then clears the
window to a different color every frame, so you'll effectively get a window
that's smoothly fading between colors.

View File

@@ -0,0 +1,68 @@
/*
* This example code creates an SDL window and renderer, and then clears the
* window to a different color every frame, so you'll effectively get a window
* that's smoothly fading between colors.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Renderer Clear", "1.0", "com.example.renderer-clear");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/clear", 640, 480, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const double now = ((double)SDL_GetTicks()) / 1000.0; /* convert from milliseconds to seconds. */
/* choose the color for the frame we will draw. The sine wave trick makes it fade between colors smoothly. */
const float red = (float) (0.5 + 0.5 * SDL_sin(now));
const float green = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 2 / 3));
const float blue = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 4 / 3));
SDL_SetRenderDrawColorFloat(renderer, red, green, blue, SDL_ALPHA_OPAQUE_FLOAT); /* new color, full alpha. */
/* clear the window to the draw color. */
SDL_RenderClear(renderer);
/* put the newly-cleared rendering on the screen. */
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,7 @@
This example creates an SDL window and renderer, and then draws some lines,
rectangles and points to it every frame.
This is just a quick overview of simple drawing primitives; futher examples
will explore them in more detail.

View File

@@ -0,0 +1,95 @@
/*
* This example creates an SDL window and renderer, and then draws some lines,
* rectangles and points to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_FPoint points[500];
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
int i;
SDL_SetAppMetadata("Example Renderer Primitives", "1.0", "com.example.renderer-primitives");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/primitives", 640, 480, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* set up some random points */
for (i = 0; i < SDL_arraysize(points); i++) {
points[i].x = (SDL_randf() * 440.0f) + 100.0f;
points[i].y = (SDL_randf() * 280.0f) + 100.0f;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect rect;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 33, 33, 33, SDL_ALPHA_OPAQUE); /* dark gray, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* draw a filled rectangle in the middle of the canvas. */
SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */
rect.x = rect.y = 100;
rect.w = 440;
rect.h = 280;
SDL_RenderFillRect(renderer, &rect);
/* draw some points across the canvas. */
SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE); /* red, full alpha */
SDL_RenderPoints(renderer, points, SDL_arraysize(points));
/* draw a unfilled rectangle in-set a little bit. */
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */
rect.x += 30;
rect.y += 30;
rect.w -= 60;
rect.h -= 60;
SDL_RenderRect(renderer, &rect);
/* draw two lines in an X across the whole canvas. */
SDL_SetRenderDrawColor(renderer, 255, 255, 0, SDL_ALPHA_OPAQUE); /* yellow, full alpha */
SDL_RenderLine(renderer, 0, 0, 640, 480);
SDL_RenderLine(renderer, 0, 480, 640, 0);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a something
roughly like a Christmas tree with nothing but lines, every frame.

View File

@@ -0,0 +1,93 @@
/*
* This example creates an SDL window and renderer, and then draws some lines
* to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Renderer Lines", "1.0", "com.example.renderer-lines");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/lines", 640, 480, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
int i;
/* Lines (line segments, really) are drawn in terms of points: a set of
X and Y coordinates, one set for each end of the line.
(0, 0) is the top left of the window, and larger numbers go down
and to the right. This isn't how geometry works, but this is pretty
standard in 2D graphics. */
static const SDL_FPoint line_points[] = {
{ 100, 354 }, { 220, 230 }, { 140, 230 }, { 320, 100 }, { 500, 230 },
{ 420, 230 }, { 540, 354 }, { 400, 354 }, { 100, 354 }
};
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 100, 100, 100, SDL_ALPHA_OPAQUE); /* grey, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* You can draw lines, one at a time, like these brown ones... */
SDL_SetRenderDrawColor(renderer, 127, 49, 32, SDL_ALPHA_OPAQUE);
SDL_RenderLine(renderer, 240, 450, 400, 450);
SDL_RenderLine(renderer, 240, 356, 400, 356);
SDL_RenderLine(renderer, 240, 356, 240, 450);
SDL_RenderLine(renderer, 400, 356, 400, 450);
/* You can also draw a series of connected lines in a single batch... */
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE);
SDL_RenderLines(renderer, line_points, SDL_arraysize(line_points));
/* here's a bunch of lines drawn out from a center point in a circle. */
/* we randomize the color of each line, so it functions as animation. */
for (i = 0; i < 360; i++) {
const float size = 30.0f;
const float x = 320.0f;
const float y = 95.0f - (size / 2.0f);
SDL_SetRenderDrawColor(renderer, SDL_rand(256), SDL_rand(256), SDL_rand(256), SDL_ALPHA_OPAQUE);
SDL_RenderLine(renderer, x, y, x + SDL_sinf((float) i) * size, y + SDL_cosf((float) i) * size);
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a bunch of
single points, moving across the screen.

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

View File

@@ -0,0 +1,118 @@
/*
* This example creates an SDL window and renderer, and then draws some points
* to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static Uint64 last_time = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define NUM_POINTS 500
#define MIN_PIXELS_PER_SECOND 30 /* move at least this many pixels per second. */
#define MAX_PIXELS_PER_SECOND 60 /* move this many pixels per second at most. */
/* (track everything as parallel arrays instead of a array of structs,
so we can pass the coordinates to the renderer in a single function call.) */
/* Points are plotted as a set of X and Y coordinates.
(0, 0) is the top left of the window, and larger numbers go down
and to the right. This isn't how geometry works, but this is pretty
standard in 2D graphics. */
static SDL_FPoint points[NUM_POINTS];
static float point_speeds[NUM_POINTS];
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
int i;
SDL_SetAppMetadata("Example Renderer Points", "1.0", "com.example.renderer-points");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/points", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* set up the data for a bunch of points. */
for (i = 0; i < SDL_arraysize(points); i++) {
points[i].x = SDL_randf() * ((float) WINDOW_WIDTH);
points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT);
point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND));
}
last_time = SDL_GetTicks();
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const Uint64 now = SDL_GetTicks();
const float elapsed = ((float) (now - last_time)) / 1000.0f; /* seconds since last iteration */
int i;
/* let's move all our points a little for a new frame. */
for (i = 0; i < SDL_arraysize(points); i++) {
const float distance = elapsed * point_speeds[i];
points[i].x += distance;
points[i].y += distance;
if ((points[i].x >= WINDOW_WIDTH) || (points[i].y >= WINDOW_HEIGHT)) {
/* off the screen; restart it elsewhere! */
if (SDL_rand(2)) {
points[i].x = SDL_randf() * ((float) WINDOW_WIDTH);
points[i].y = 0.0f;
} else {
points[i].x = 0.0f;
points[i].y = SDL_randf() * ((float) WINDOW_HEIGHT);
}
point_speeds[i] = MIN_PIXELS_PER_SECOND + (SDL_randf() * (MAX_PIXELS_PER_SECOND - MIN_PIXELS_PER_SECOND));
}
}
last_time = now;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */
SDL_RenderPoints(renderer, points, SDL_arraysize(points)); /* draw all the points! */
/* You can also draw single points with SDL_RenderPoint(), but it's
cheaper (sometimes significantly so) to do them all at once. */
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, and then draws a few
rectangles that change size each frame.

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -0,0 +1,112 @@
/*
* This example creates an SDL window and renderer, and then draws some
* rectangles to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Renderer Rectangles", "1.0", "com.example.renderer-rectangles");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/rectangles", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect rects[16];
const Uint64 now = SDL_GetTicks();
int i;
/* we'll have the rectangles grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Rectangles are comprised of set of X and Y coordinates, plus width and
height. (0, 0) is the top left of the window, and larger numbers go
down and to the right. This isn't how geometry works, but this is
pretty standard in 2D graphics. */
/* Let's draw a single rectangle (square, really). */
rects[0].x = rects[0].y = 100;
rects[0].w = rects[0].h = 100 + (100 * scale);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE); /* red, full alpha */
SDL_RenderRect(renderer, &rects[0]);
/* Now let's draw several rectangles with one function call. */
for (i = 0; i < 3; i++) {
const float size = (i+1) * 50.0f;
rects[i].w = rects[i].h = size + (size * scale);
rects[i].x = (WINDOW_WIDTH - rects[i].w) / 2; /* center it. */
rects[i].y = (WINDOW_HEIGHT - rects[i].h) / 2; /* center it. */
}
SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */
SDL_RenderRects(renderer, rects, 3); /* draw three rectangles at once */
/* those were rectangle _outlines_, really. You can also draw _filled_ rectangles! */
rects[0].x = 400;
rects[0].y = 50;
rects[0].w = 100 + (100 * scale);
rects[0].h = 50 + (50 * scale);
SDL_SetRenderDrawColor(renderer, 0, 0, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */
SDL_RenderFillRect(renderer, &rects[0]);
/* ...and also fill a bunch of rectangles at once... */
for (i = 0; i < SDL_arraysize(rects); i++) {
const float w = (float) (WINDOW_WIDTH / SDL_arraysize(rects));
const float h = i * 8.0f;
rects[i].x = i * w;
rects[i].y = WINDOW_HEIGHT - h;
rects[i].w = w;
rects[i].h = h;
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */
SDL_RenderFillRects(renderer, rects, SDL_arraysize(rects));
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a
.bmp file, and then draws it a few times each frame.

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

View File

@@ -0,0 +1,127 @@
/*
* This example creates an SDL window and renderer, and then draws some
* textures to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Textures", "1.0", "com.example.renderer-textures");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
/* we'll have some textures move around over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Just draw the static texture a few times. You can think of it like a
stamp, there isn't a limit to the number of times you can draw with it. */
/* top left */
dst_rect.x = (100.0f * scale);
dst_rect.y = 0.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* center this one. */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* bottom right. */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) - (100.0f * scale);
dst_rect.y = (float) (WINDOW_HEIGHT - texture_height);
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, then a streaming texture that
it will update every frame before drawing it to the screen.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,109 @@
/*
* This example creates an SDL window and renderer, and then draws a streaming
* texture to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
#define TEXTURE_SIZE 150
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Renderer Streaming Textures", "1.0", "com.example.renderer-streaming-textures");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/streaming-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, TEXTURE_SIZE, TEXTURE_SIZE);
if (!texture) {
SDL_Log("Couldn't create streaming texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
SDL_Surface *surface = NULL;
/* we'll have some color move around over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* To update a streaming texture, you need to lock it first. This gets you access to the pixels.
Note that this is considered a _write-only_ operation: the buffer you get from locking
might not acutally have the existing contents of the texture, and you have to write to every
locked pixel! */
/* You can use SDL_LockTexture() to get an array of raw pixels, but we're going to use
SDL_LockTextureToSurface() here, because it wraps that array in a temporary SDL_Surface,
letting us use the surface drawing functions instead of lighting up individual pixels. */
if (SDL_LockTextureToSurface(texture, NULL, &surface)) {
SDL_Rect r;
SDL_FillSurfaceRect(surface, NULL, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 0, 0)); /* make the whole surface black */
r.w = TEXTURE_SIZE;
r.h = TEXTURE_SIZE / 10;
r.x = 0;
r.y = (int) (((float) (TEXTURE_SIZE - r.h)) * ((scale + 1.0f) / 2.0f));
SDL_FillSurfaceRect(surface, &r, SDL_MapRGB(SDL_GetPixelFormatDetails(surface->format), NULL, 0, 255, 0)); /* make a strip of the surface green */
SDL_UnlockTexture(texture); /* upload the changes (and frees the temporary surface)! */
}
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 66, 66, 66, SDL_ALPHA_OPAQUE); /* grey, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Just draw the static texture a few times. You can think of it like a
stamp, there isn't a limit to the number of times you can draw with it. */
/* Center this one. It'll draw the latest version of the texture we drew while it was locked. */
dst_rect.x = ((float) (WINDOW_WIDTH - TEXTURE_SIZE)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - TEXTURE_SIZE)) / 2.0f;
dst_rect.w = dst_rect.h = (float) TEXTURE_SIZE;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
file, and then draws it, rotating around the center of the screen.

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

View File

@@ -0,0 +1,113 @@
/*
* This example creates an SDL window and renderer, and then draws some
* rotated textures to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Rotating Textures", "1.0", "com.example.renderer-rotating-textures");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/rotating-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FPoint center;
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
/* we'll have a texture rotate around over 2 seconds (2000 milliseconds). 360 degrees in a circle! */
const float rotation = (((float) ((int) (now % 2000))) / 2000.0f) * 360.0f;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Center this one, and draw it with some rotation so it spins! */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
/* rotate it around the center of the texture; you can rotate it from a different point, too! */
center.x = texture_width / 2.0f;
center.y = texture_height / 2.0f;
SDL_RenderTextureRotated(renderer, texture, NULL, &dst_rect, rotation, &center, SDL_FLIP_NONE);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
file, and then draws it, scaling it up and down.

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

View File

@@ -0,0 +1,110 @@
/*
* This example creates an SDL window and renderer, and then draws some
* textures to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Scaling Textures", "1.0", "com.example.renderer-scaling-textures");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/scaling-textures", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const Uint64 now = SDL_GetTicks();
/* we'll have the texture grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* center this one and make it grow and shrink. */
dst_rect.w = (float) texture_width + (texture_width * scale);
dst_rect.h = (float) texture_height + (texture_height * scale);
dst_rect.x = (WINDOW_WIDTH - dst_rect.w) / 2.0f;
dst_rect.y = (WINDOW_HEIGHT - dst_rect.h) / 2.0f;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a .bmp
file, and then draws geometry (arbitrary polygons) using it.

View File

@@ -0,0 +1,166 @@
/*
* This example creates an SDL window and renderer, and then draws some
* geometry (arbitrary polygons) to it every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Geometry", "1.0", "com.example.renderer-geometry");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/geometry", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const Uint64 now = SDL_GetTicks();
/* we'll have the triangle grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction;
const float size = 200.0f + (200.0f * scale);
SDL_Vertex vertices[4];
int i;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Draw a single triangle with a different color at each vertex. Center this one and make it grow and shrink. */
/* You always draw triangles with this, but you can string triangles together to form polygons. */
SDL_zeroa(vertices);
vertices[0].position.x = ((float) WINDOW_WIDTH) / 2.0f;
vertices[0].position.y = (((float) WINDOW_HEIGHT) - size) / 2.0f;
vertices[0].color.r = 1.0f;
vertices[0].color.a = 1.0f;
vertices[1].position.x = (((float) WINDOW_WIDTH) + size) / 2.0f;
vertices[1].position.y = (((float) WINDOW_HEIGHT) + size) / 2.0f;
vertices[1].color.g = 1.0f;
vertices[1].color.a = 1.0f;
vertices[2].position.x = (((float) WINDOW_WIDTH) - size) / 2.0f;
vertices[2].position.y = (((float) WINDOW_HEIGHT) + size) / 2.0f;
vertices[2].color.b = 1.0f;
vertices[2].color.a = 1.0f;
SDL_RenderGeometry(renderer, NULL, vertices, 3, NULL, 0);
/* you can also map a texture to the geometry! Texture coordinates go from 0.0f to 1.0f. That will be the location
in the texture bound to this vertex. */
SDL_zeroa(vertices);
vertices[0].position.x = 10.0f;
vertices[0].position.y = 10.0f;
vertices[0].color.r = vertices[0].color.g = vertices[0].color.b = vertices[0].color.a = 1.0f;
vertices[0].tex_coord.x = 0.0f;
vertices[0].tex_coord.y = 0.0f;
vertices[1].position.x = 150.0f;
vertices[1].position.y = 10.0f;
vertices[1].color.r = vertices[1].color.g = vertices[1].color.b = vertices[1].color.a = 1.0f;
vertices[1].tex_coord.x = 1.0f;
vertices[1].tex_coord.y = 0.0f;
vertices[2].position.x = 10.0f;
vertices[2].position.y = 150.0f;
vertices[2].color.r = vertices[2].color.g = vertices[2].color.b = vertices[2].color.a = 1.0f;
vertices[2].tex_coord.x = 0.0f;
vertices[2].tex_coord.y = 1.0f;
SDL_RenderGeometry(renderer, texture, vertices, 3, NULL, 0);
/* Did that only draw half of the texture? You can do multiple triangles sharing some vertices,
using indices, to get the whole thing on the screen: */
/* Let's just move this over so it doesn't overlap... */
for (i = 0; i < 3; i++) {
vertices[i].position.x += 450;
}
/* we need one more vertex, since the two triangles can share two of them. */
vertices[3].position.x = 600.0f;
vertices[3].position.y = 150.0f;
vertices[3].color.r = vertices[3].color.g = vertices[3].color.b = vertices[3].color.a = 1.0f;
vertices[3].tex_coord.x = 1.0f;
vertices[3].tex_coord.y = 1.0f;
/* And an index to tell it to reuse some of the vertices between triangles... */
{
/* 4 vertices, but 6 actual places they used. Indices need less bandwidth to transfer and can reorder vertices easily! */
const int indices[] = { 0, 1, 2, 1, 2, 3 };
SDL_RenderGeometry(renderer, texture, vertices, 4, indices, SDL_arraysize(indices));
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -0,0 +1,3 @@
This example creates an SDL window and renderer, loads a texture from a
.bmp file, and then draws it a few times each frame, adjusting the colors.

View File

@@ -0,0 +1,134 @@
/*
* This example creates an SDL window and renderer, and then draws some
* textures to it every frame, adjusting their color.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Color Mods", "1.0", "com.example.renderer-color-mods");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/color-mods", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect;
const double now = ((double)SDL_GetTicks()) / 1000.0; /* convert from milliseconds to seconds. */
/* choose the modulation values for the center texture. The sine wave trick makes it fade between colors smoothly. */
const float red = (float) (0.5 + 0.5 * SDL_sin(now));
const float green = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 2 / 3));
const float blue = (float) (0.5 + 0.5 * SDL_sin(now + SDL_PI_D * 4 / 3));
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Just draw the static texture a few times. You can think of it like a
stamp, there isn't a limit to the number of times you can draw with it. */
/* Color modulation multiplies each pixel's red, green, and blue intensities by the mod values,
so multiplying by 1.0f will leave a color intensity alone, 0.0f will shut off that color
completely, etc. */
/* top left; let's make this one blue! */
dst_rect.x = 0.0f;
dst_rect.y = 0.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_SetTextureColorModFloat(texture, 0.0f, 0.0f, 1.0f); /* kill all red and green. */
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* center this one, and have it cycle through red/green/blue modulations. */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_SetTextureColorModFloat(texture, red, green, blue);
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* bottom right; let's make this one red! */
dst_rect.x = (float) (WINDOW_WIDTH - texture_width);
dst_rect.y = (float) (WINDOW_HEIGHT - texture_height);
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
SDL_SetTextureColorModFloat(texture, 1.0f, 0.0f, 0.0f); /* kill all green and blue. */
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View File

@@ -0,0 +1,4 @@
This example creates an SDL window and renderer, loads a texture
from a .bmp file, and then draws it a few times each frame, adjusting
the viewport before each draw.

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

View File

@@ -0,0 +1,136 @@
/*
* This example creates an SDL window and renderer, and then draws some
* textures to it every frame, adjusting the viewport.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Viewport", "1.0", "com.example.renderer-viewport");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/viewport", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
SDL_FRect dst_rect = { 0, 0, (float) texture_width, (float) texture_height };
SDL_Rect viewport;
/* Setting a viewport has the effect of limiting the area that rendering
can happen, and making coordinate (0, 0) live somewhere else in the
window. It does _not_ scale rendering to fit the viewport. */
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Draw once with the whole window as the viewport. */
viewport.x = 0;
viewport.y = 0;
viewport.w = WINDOW_WIDTH / 2;
viewport.h = WINDOW_HEIGHT / 2;
SDL_SetRenderViewport(renderer, NULL); /* NULL means "use the whole window" */
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* top right quarter of the window. */
viewport.x = WINDOW_WIDTH / 2;
viewport.y = WINDOW_HEIGHT / 2;
viewport.w = WINDOW_WIDTH / 2;
viewport.h = WINDOW_HEIGHT / 2;
SDL_SetRenderViewport(renderer, &viewport);
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* bottom 20% of the window. Note it clips the width! */
viewport.x = 0;
viewport.y = WINDOW_HEIGHT - (WINDOW_HEIGHT / 5);
viewport.w = WINDOW_WIDTH / 5;
viewport.h = WINDOW_HEIGHT / 5;
SDL_SetRenderViewport(renderer, &viewport);
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
/* what happens if you try to draw above the viewport? It should clip! */
viewport.x = 100;
viewport.y = 200;
viewport.w = WINDOW_WIDTH;
viewport.h = WINDOW_HEIGHT;
SDL_SetRenderViewport(renderer, &viewport);
dst_rect.y = -50;
SDL_RenderTexture(renderer, texture, NULL, &dst_rect);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

View File

@@ -0,0 +1,5 @@
This example creates an SDL window and renderer, loads a texture
from a .bmp file, and stretches it across the window. Each frame, we move
the clipping rectangle around, so only a small square of the texture is
actually drawn.

View File

@@ -0,0 +1,137 @@
/*
* This example creates an SDL window and renderer, and then draws a scene
* to it every frame, while sliding around a clipping rectangle.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define CLIPRECT_SIZE 250
#define CLIPRECT_SPEED 200 /* pixels per second */
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static SDL_FPoint cliprect_position;
static SDL_FPoint cliprect_direction;
static Uint64 last_time = 0;
/* A lot of this program is examples/renderer/02-primitives, so we have a good
visual that we can slide a clip rect around. The actual new magic in here
is the SDL_SetRenderClipRect() function. */
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Clipping Rectangle", "1.0", "com.example.renderer-cliprect");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/cliprect", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
cliprect_direction.x = cliprect_direction.y = 1.0f;
last_time = SDL_GetTicks();
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const SDL_Rect cliprect = { (int) SDL_roundf(cliprect_position.x), (int) SDL_roundf(cliprect_position.y), CLIPRECT_SIZE, CLIPRECT_SIZE };
const Uint64 now = SDL_GetTicks();
const float elapsed = ((float) (now - last_time)) / 1000.0f; /* seconds since last iteration */
const float distance = elapsed * CLIPRECT_SPEED;
/* Set a new clipping rectangle position */
cliprect_position.x += distance * cliprect_direction.x;
if (cliprect_position.x < 0.0f) {
cliprect_position.x = 0.0f;
cliprect_direction.x = 1.0f;
} else if (cliprect_position.x >= (WINDOW_WIDTH - CLIPRECT_SIZE)) {
cliprect_position.x = (WINDOW_WIDTH - CLIPRECT_SIZE) - 1;
cliprect_direction.x = -1.0f;
}
cliprect_position.y += distance * cliprect_direction.y;
if (cliprect_position.y < 0.0f) {
cliprect_position.y = 0.0f;
cliprect_direction.y = 1.0f;
} else if (cliprect_position.y >= (WINDOW_HEIGHT - CLIPRECT_SIZE)) {
cliprect_position.y = (WINDOW_HEIGHT - CLIPRECT_SIZE) - 1;
cliprect_direction.y = -1.0f;
}
SDL_SetRenderClipRect(renderer, &cliprect);
last_time = now;
/* okay, now draw! */
/* Note that SDL_RenderClear is _not_ affected by the clipping rectangle! */
SDL_SetRenderDrawColor(renderer, 33, 33, 33, SDL_ALPHA_OPAQUE); /* grey, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* stretch the texture across the entire window. Only the piece in the
clipping rectangle will actually render, though! */
SDL_RenderTexture(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -0,0 +1,12 @@
This example creates an SDL window and renderer, and draws a
rotating texture to it, reads back the rendered pixels, converts them to
black and white, and then draws the converted image to a corner of the
screen.
This isn't necessarily an efficient thing to do--in real life one might
want to do this sort of thing with a render target--but it's just a visual
example of how to use SDL_RenderReadPixels().
A better, but less visual, use of SDL_RenderReadPixels() is to make
screenshots: you grab the current contents of the screen, and save the pixels
as a bitmap file or whatever.

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 KiB

View File

@@ -0,0 +1,178 @@
/*
* This example creates an SDL window and renderer, and draws a
* rotating texture to it, reads back the rendered pixels, converts them to
* black and white, and then draws the converted image to a corner of the
* screen.
*
* This isn't necessarily an efficient thing to do--in real life one might
* want to do this sort of thing with a render target--but it's just a visual
* example of how to use SDL_RenderReadPixels().
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static int texture_width = 0;
static int texture_height = 0;
static SDL_Texture *converted_texture = NULL;
static int converted_texture_width = 0;
static int converted_texture_height = 0;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Surface *surface = NULL;
char *bmp_path = NULL;
SDL_SetAppMetadata("Example Renderer Read Pixels", "1.0", "com.example.renderer-read-pixels");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/read-pixels", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
/* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D
engines refer to these as "sprites." We'll do a static texture (upload once, draw many
times) with data from a bitmap file. */
/* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access.
Load a .bmp into a surface, move it to a texture from there. */
SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */
surface = SDL_LoadBMP(bmp_path);
if (!surface) {
SDL_Log("Couldn't load bitmap: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_free(bmp_path); /* done with this, the file is loaded. */
texture_width = surface->w;
texture_height = surface->h;
texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
SDL_Log("Couldn't create static texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const Uint64 now = SDL_GetTicks();
SDL_Surface *surface;
SDL_FPoint center;
SDL_FRect dst_rect;
/* we'll have a texture rotate around over 2 seconds (2000 milliseconds). 360 degrees in a circle! */
const float rotation = (((float) ((int) (now % 2000))) / 2000.0f) * 360.0f;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Center this one, and draw it with some rotation so it spins! */
dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f;
dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f;
dst_rect.w = (float) texture_width;
dst_rect.h = (float) texture_height;
/* rotate it around the center of the texture; you can rotate it from a different point, too! */
center.x = texture_width / 2.0f;
center.y = texture_height / 2.0f;
SDL_RenderTextureRotated(renderer, texture, NULL, &dst_rect, rotation, &center, SDL_FLIP_NONE);
/* this next whole thing is _super_ expensive. Seriously, don't do this in real life. */
/* Download the pixels of what has just been rendered. This has to wait for the GPU to finish rendering it and everything before it,
and then make an expensive copy from the GPU to system RAM! */
surface = SDL_RenderReadPixels(renderer, NULL);
/* This is also expensive, but easier: convert the pixels to a format we want. */
if (surface && (surface->format != SDL_PIXELFORMAT_RGBA8888) && (surface->format != SDL_PIXELFORMAT_BGRA8888)) {
SDL_Surface *converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA8888);
SDL_DestroySurface(surface);
surface = converted;
}
if (surface) {
/* Rebuild converted_texture if the dimensions have changed (window resized, etc). */
if ((surface->w != converted_texture_width) || (surface->h != converted_texture_height)) {
SDL_DestroyTexture(converted_texture);
converted_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, surface->w, surface->h);
if (!converted_texture) {
SDL_Log("Couldn't (re)create conversion texture: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
converted_texture_width = surface->w;
converted_texture_height = surface->h;
}
/* Turn each pixel into either black or white. This is a lousy technique but it works here.
In real life, something like Floyd-Steinberg dithering might work
better: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering*/
int x, y;
for (y = 0; y < surface->h; y++) {
Uint32 *pixels = (Uint32 *) (((Uint8 *) surface->pixels) + (y * surface->pitch));
for (x = 0; x < surface->w; x++) {
Uint8 *p = (Uint8 *) (&pixels[x]);
const Uint32 average = (((Uint32) p[1]) + ((Uint32) p[2]) + ((Uint32) p[3])) / 3;
if (average == 0) {
p[0] = p[3] = 0xFF; p[1] = p[2] = 0; /* make pure black pixels red. */
} else {
p[1] = p[2] = p[3] = (average > 50) ? 0xFF : 0x00; /* make everything else either black or white. */
}
}
}
/* upload the processed pixels back into a texture. */
SDL_UpdateTexture(converted_texture, NULL, surface->pixels, surface->pitch);
SDL_DestroySurface(surface);
/* draw the texture to the top-left of the screen. */
dst_rect.x = dst_rect.y = 0.0f;
dst_rect.w = ((float) WINDOW_WIDTH) / 4.0f;
dst_rect.h = ((float) WINDOW_HEIGHT) / 4.0f;
SDL_RenderTexture(renderer, converted_texture, NULL, &dst_rect);
}
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
SDL_DestroyTexture(converted_texture);
SDL_DestroyTexture(texture);
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -0,0 +1,4 @@
This example creates an SDL window and renderer, and draws some text
using SDL_RenderDebugText(). This is not quality text rendering, but it can
be helpful for simple apps, debugging, or showing something in a pinch.

View File

@@ -0,0 +1,80 @@
/*
* This example creates an SDL window and renderer, and then draws some text
* using SDL_RenderDebugText() every frame.
*
* This code is public domain. Feel free to use it for any purpose!
*/
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* We will use this renderer to draw into this window every frame. */
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
/* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_SetAppMetadata("Example Renderer Debug Texture", "1.0", "com.example.renderer-debug-text");
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("examples/renderer/debug-text", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
}
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate)
{
const int charsize = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
/* as you can see from this, rendering draws over whatever was drawn before it. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */
SDL_RenderDebugText(renderer, 272, 100, "Hello world!");
SDL_RenderDebugText(renderer, 224, 150, "This is some debug text.");
SDL_SetRenderDrawColor(renderer, 51, 102, 255, SDL_ALPHA_OPAQUE); /* light blue, full alpha */
SDL_RenderDebugText(renderer, 184, 200, "You can do it in different colors.");
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */
SDL_SetRenderScale(renderer, 4.0f, 4.0f);
SDL_RenderDebugText(renderer, 14, 65, "It can be scaled.");
SDL_SetRenderScale(renderer, 1.0f, 1.0f);
SDL_RenderDebugText(renderer, 64, 350, "This only does ASCII chars. So this laughing emoji won't draw: 🤣");
SDL_RenderDebugTextFormat(renderer, (float) ((WINDOW_WIDTH - (charsize * 46)) / 2), 400, "(This program has been running for %" SDL_PRIu64 " seconds.)", SDL_GetTicks() / 1000);
SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */
}
/* This function runs once at shutdown. */
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
/* SDL will clean up the window/renderer for us. */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB