You do not need to build SDL3_image because SDL3 has a native support for loading PNG images:
const char *texturePath = "./assets/images/right-arrow.png";
SDL_Surface *surface = SDL_LoadPNG(texturePath);
if (!surface)
{
SDL_Log("PNG load failed: %s: %s\n", texturePath, SDL_GetError());
return SDL_APP_FAILURE;
}
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_DestroySurface(surface);
main.c
#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <stdio.h>
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO))
{
SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!SDL_CreateWindowAndRenderer("Example", 400, 400, 0, &window, &renderer))
{
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_SetRenderVSync(renderer, 1);
const char *texturePath = "./assets/images/right-arrow.png";
SDL_Surface *surface = SDL_LoadPNG(texturePath);
if (!surface)
{
SDL_Log("PNG load failed: %s: %s\n", texturePath, SDL_GetError());
return SDL_APP_FAILURE;
}
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_DestroySurface(surface);
return SDL_APP_CONTINUE;
}
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;
}
SDL_AppResult SDL_AppIterate(void *appstate)
{
// Clear the screen
SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255);
SDL_RenderClear(renderer);
SDL_FRect srcRect = { 0, 0, 512, 512 };
SDL_FRect destRect = { 50, 50, 100, 100 };
SDL_RenderTexture(renderer, texture, &srcRect, &destRect);
// Update the screen
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
// SDL will clean up the window/renderer for us
SDL_DestroyTexture(texture);
}
You need to embed your image files to WASM like this:
if (EMSCRIPTEN)
target_link_options("app" PRIVATE "SHELL:--embed-file \"${CMAKE_CURRENT_SOURCE_DIR}/assets/images/right-arrow.png@/assets/images/right-arrow.png\"")
set_property(TARGET "app" APPEND PROPERTY LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets/images/right-arrow.png")
endif()
CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(finish-native-png-loader-wasm-sdl3-c)
# Set the C standard (must be set before add_executable)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Set the name of the future application (on Windows this would be app.exe,
# while for the web it will be app.js / app.wasm)
add_executable(app)
# Specify the exact location of the SDL3 library configuration files
# The variable name must strictly follow the pattern: LibraryName_DIR
set(SDL3_DIR "C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3")
# Check for the presence of libraries in the system
# If they are not found, CMake will abort the configuration with an error
# REQUIRED indicates that the package is mandatory for the build
find_package(SDL3 REQUIRED)
# Link the libraries to our application (configures linking and include paths)
target_link_libraries(app PRIVATE SDL3::SDL3)
# Add source code to the project
target_sources(app
PRIVATE
src/main.c
)
# Embed the image into the app.wasm file
if (EMSCRIPTEN)
# Use the SHELL: prefix to pass the --embed-file option to the linker
target_link_options("app" PRIVATE "SHELL:--embed-file \"${CMAKE_CURRENT_SOURCE_DIR}/assets/images/right-arrow.png@/assets/images/right-arrow.png\"")
# Ensure the target is relinked if the image file changes
set_property(TARGET "app" APPEND PROPERTY LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets/images/right-arrow.png")
endif()
