Форум программистов, компьютерный форум, киберфорум
8Observer8
Войти
Регистрация
Восстановить пароль

SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf

Запись от 8Observer8 размещена 01.02.2026 в 00:47. Обновил(-а) 8Observer8 01.02.2026 в 07:40
Показов 2844 Комментарии 0

Содержание блога

В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный хостинг Vercel из консоли парой консольных команд: "vercel login" и "vercel". Финальный результат инструкции в браузере: запустить демку в один клик. Исходники финальной демки: finish-hello-ttf-wasm-sdl3-c.zip

Если у вас не установлены Emscripten SDK и CMake, то установите их по следующей инструкции и выполните "hello world" инструкцию там же: Установка Emscripten SDK (emsdk) и CMake

  • Скачайте стартовый пример: start-hello-ttf-wasm-sdl3-c.zip. Этот пример мы создали в инструкции по установке: Установка Emscripten SDK - обязательно пойдите "hello world" инструкцию там же
  • Откройте этот пример в каком-нибудь редакторе кода. Например, в Notepad++. Мне больше всего нравится редактор кода Sublime Text 4: https://www.sublimetext.com/download. ST4 почти такой же лёгкий, как Notepad++ и гораздо удобнее. Добавьте путь с ST4 в Path и вы сможете запускать ST4 из консоли, открывая проект в текущей папке, командой: subl . (точка означает, что нужно открыть текущую папку в ST4)
    Название: cecfe6687db475bc69135f0f0e7532f3268c6d28.png
Просмотров: 1821

Размер: 5.6 Кб
  • Скачайте архив SDL3-devel-3.4.0-wasm.zip - это SDL3-библиотека, которая собрана из исходников для Wasm-проектов с помощью emsdk 4.0.15. У вас должна быть установлена и активирована именно эта версия emsdk
  • Скачайте архив SDL3_ttf-devel-3.2.2-wasm.zip - эта библиотека для SDL3-проектов для работы с TTF-шрифтами, которая собрана для Wasm-проектов с помощью emsdk 4.0.15
  • Скачайте архив freetype-2.13.3-wasm.zip - библиотека FreeType необходима для работы SDL3_ttf
  • Извлеките архивы в текущую папку и перенесите три извлечённые папки на какой-нибудь локальный диск, наприме, можете создать папку "libs" на системном диске C и скопировать эти папки в папку "libs"
  • Откройте файл CMakeLists.txt и добавьте код для подключения библиотек SDL3, SDL3_ttf и FreeType (проверьте пути в этом файле - правильные ли они на вашем компьютере):
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    cmake_minimum_required(VERSION 3.21)
    project(start-hello-ttf-wasm-sdl3-c)
     
    # Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)
    add_executable(app)
     
    # Устанавливаем стандарт C
    set(CMAKE_C_STANDARD 11)
     
    # Подсказываем CMake, где искать конфигурационные файлы библиотек
    set(SDL3_DIR "C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3")
    set(SDL3_ttf_DIR "C:/libs/SDL3_ttf-devel-3.2.2-wasm/lib/cmake/SDL3_ttf")
    set(FREETYPE_INCLUDE_DIRS "C:/libs/freetype-2.13.3-wasm/include")
    set(FREETYPE_LIBRARY "C:/libs/freetype-2.13.3-wasm/lib/libfreetype.a")
     
    # Загружаем настройки пакетов (параметры компиляции и пути к заголовкам)
    find_package(SDL3 REQUIRED)
    find_package(SDL3_ttf REQUIRED)
     
    # Привязываем библиотеки к нашему приложению (настройка линковки и путей include)
    target_link_libraries(app PRIVATE SDL3_ttf::SDL3_ttf SDL3::SDL3)
     
    # Добавляем исходный код к проекту
    target_sources(app
        PRIVATE
        src/main.c
    )
  • Пример пока пустой (в main.c только базовый код вывода "hello world" в консоль), но проверьте работоспособность. В инструкции по установке Emscripten SDK мы запускали этот пример командами:
    Bash
    1
    2
    3
    
    config-web
    build-web
    http-server -c-1
  • Локальный сервер выведет адреса, которые скопировать в адресную строку браузера, например, 127.0.0.1:8080 (либо можно ввести localhost:8080)
  • Перейдите в браузер и введите адрес: localhost:8080 и нажмите Enter
  • Вы увидите результат работы программы в консоли браузера, если нажмёте: Ctrl+Shift+J в Chrome и Edge, либо Ctrl+Shift+K в FireFox
  • Запустите в корне папки проекта вторую консоль, чтобы дальше можно было переконфигурировать и собирать проект в этой консоли, а в первой консоли пусть запущен локальные сервер
  • Откройте файл src/main.c и добавим код с базовыми четырьмя функциями SDL3. Этот код создаёт холст для рисования размеров 400 на 400 пикселя, заливает его тёмно-серым цветом и выводит в консоль версию SDL3:
    C
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    
    #define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()
    #include <SDL3/SDL.h>
    #include <SDL3/SDL_main.h>
    #include <SDL3_ttf/SDL_ttf.h>
    #include <stdio.h>
     
    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[])
    {
        if (!SDL_Init(SDL_INIT_VIDEO))
        {
            SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
            return SDL_APP_FAILURE;
        }
     
        const char *title = "Example";
        if (!SDL_CreateWindowAndRenderer(title, 400, 400, 0, &window, &renderer))
        {
            SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
            return SDL_APP_FAILURE;
        }
     
        SDL_SetRenderVSync(renderer, 1);
     
        // --- Print SDL versions ---
        printf("Compiled SDL3 version: %d.%d.%d\n",
            SDL_MAJOR_VERSION,
            SDL_MINOR_VERSION,
            SDL_MICRO_VERSION);
        // Get the version of the SDL library linked at runtime
        int v = SDL_GetVersion();
        printf("Linked SDL3 version:   %d.%d.%d\n", SDL_VERSIONNUM_MAJOR(v),
            SDL_VERSIONNUM_MINOR(v), SDL_VERSIONNUM_MICRO(v));
     
        return SDL_APP_CONTINUE;
    }
     
    // 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;
    }
     
    // This function runs once per frame, and is the heart of the program
    SDL_AppResult SDL_AppIterate(void *appstate)
    {
        // Clear the screen
        SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255);
        SDL_RenderClear(renderer);
     
        // Update the screen
        SDL_RenderPresent(renderer);
        return SDL_APP_CONTINUE;
    }
     
    // This function runs once at shutdown
    void SDL_AppQuit(void *appstate, SDL_AppResult result)
    {
        if (renderer)
        {
            SDL_DestroyRenderer(renderer);
            renderer = NULL;
        }
     
        if (window)
        {
            SDL_DestroyWindow(window);
            window = NULL;
        }
     
        SDL_Quit();
    }
  • Откройте в редакторе кода файл "public/index.html" и добавьте элемент <canvas> и удалите элемент <title> (потому что Title задаются в функции SDL_CreateWindowAndRenderer - в первом аргументе этой функции):

    index.html

    PHP/HTML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    <!DOCTYPE html>
     
    <html>
     
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
     
    <body>
        <canvas id="canvas"></canvas>
     
        <script async src="./js/app.js"></script>
    </body>
  • Введите команды конфигурирования и сборки:
    Bash
    1
    2
    
    config-web
    build-web
  • Перейдите в браузер и введите адрес: localhost:8080 и нажмите Enter
  • Вы увидите холст размером 400 на 400 пикселей тёрмно-серого цвета. Если откроете консоль браузера, то увидите вывод версии SDL3:
    Code
    1
    2
    
    Compiled SDL3 version: 3.4.0
    Linked SDL3 version:   3.4.0
  • Скачайте бесплатный шрифт TTF: LiberationSans-Regular.zip (файл был взят по ссылке)
  • В корне проекта создайте папку "assets", а в внутри этой папки создайте папку "fonts"
  • Перенесите извлечённый файл LiberationSans-Regular.ttf в папку "assets/fonts"
  • Откройте файл CMakeLists.txt и скопируйте код для загрузки TTF файла в конец файла CMakeLists.txt:
    Code
    1
    2
    3
    4
    
    if (EMSCRIPTEN)
        target_link_options("app" PRIVATE "SHELL:--embed-file ${CMAKE_CURRENT_SOURCE_DIR}/assets/fonts/LiberationSans-Regular.ttf@/assets/fonts/LiberationSans-Regular.ttf")
        set_property(TARGET "app" APPEND PROPERTY LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets/fonts/LiberationSans-Regular.ttf")
    endif()
  • Примечание. Таким образом можно загружать любые ассеты: картинки, звуки, JSON-файлы и т.д. - просто копируйте код выше и меняйте пути
  • Замените весь код main.c на следующий код, который выводит текст "Привет из WebAssembly!" зелёного цвета размера 28 на холст:

    main.c

    C
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    
    #define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()
    #include <SDL3/SDL.h>
    #include <SDL3/SDL_main.h>
    #include <SDL3_ttf/SDL_ttf.h>
    #include <stdio.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;
     
    // This function runs once at startup
    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;
        }
     
        // Initialize the TTF library
        if (!TTF_Init())
        {
            SDL_Log("Couldn't initialize TTF: %s", SDL_GetError());
            return SDL_APP_FAILURE;
        }
     
        const char *title = "English Text (SDL3 / C)";
        if (!SDL_CreateWindowAndRenderer(title, 350, 350, 0, &window, &renderer))
        {
            SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
            return SDL_APP_FAILURE;
        }
     
        SDL_SetRenderVSync(renderer, 1);
     
        // --- Print SDL versions ---
        printf("Compiled SDL3 version: %d.%d.%d\n",
            SDL_MAJOR_VERSION,
            SDL_MINOR_VERSION,
            SDL_MICRO_VERSION);
        // Get the version of the SDL library linked at runtime
        int v = SDL_GetVersion();
        printf("Linked SDL3 version:   %d.%d.%d\n", SDL_VERSIONNUM_MAJOR(v),
            SDL_VERSIONNUM_MINOR(v), SDL_VERSIONNUM_MICRO(v));
     
        // --- SDL3_ttf version ---
        v = TTF_Version();
        int major = SDL_VERSIONNUM_MAJOR(v);
        int minor = SDL_VERSIONNUM_MINOR(v);
        int micro = SDL_VERSIONNUM_MICRO(v);
        printf("SDL3_ttf version:      %d.%d.%d\n", major, minor, micro);
     
        TTF_Font *font = TTF_OpenFont("assets/fonts/LiberationSans-Regular.ttf", 28);
        if (!font)
        {
            SDL_Log("TTF_OpenFont failed: %s", SDL_GetError());
            return SDL_APP_FAILURE;
        }
        SDL_Color textColor = (SDL_Color) { 0, 255, 0 };
        SDL_Surface *surface = TTF_RenderText_Blended(font, "Привет из WebAssembly!", 0, textColor);
        texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_DestroySurface(surface);
     
        return SDL_APP_CONTINUE;
    }
     
    // 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;
    }
     
    // This function runs once per frame, and is the heart of the program
    SDL_AppResult SDL_AppIterate(void *appstate)
    {
        // Set the position where you want to draw the text
        float x = 10.f;
        float y = 10.f;
     
        // Create a rectangle to hold the texture dimensions
        SDL_FRect rect;
        SDL_GetTextureSize(texture, &rect.w, &rect.h);
        rect.x = x;
        rect.y = y;
     
        // SDL_RenderTexture(renderer, texture, NULL, NULL);
        // Clear the screen
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);
     
        // Draw the text
        SDL_RenderTexture(renderer, texture, NULL, &rect);
     
        // Update the screen
        SDL_RenderPresent(renderer);
        return SDL_APP_CONTINUE;
    }
     
    // This function runs once at shutdown
    void SDL_AppQuit(void *appstate, SDL_AppResult result)
    {
        if (texture)
        {
            SDL_DestroyTexture(texture);
            texture = NULL;
        }
     
        if (renderer)
        {
            SDL_DestroyRenderer(renderer);
            renderer = NULL;
        }
     
        if (window)
        {
            SDL_DestroyWindow(window);
            window = NULL;
        }
     
        TTF_Quit();
        SDL_Quit();
    }
  • Примечание. Ещё код выше выводит в консоль версии SDL3 и SDL3_ttf:
    Code
    1
    2
    3
    
    Compiled SDL3 version: 3.4.0
    Linked SDL3 version:   3.4.0
    SDL3_ttf version:      3.2.2
  • Не смотря на то, что были изменения в файле CMakeLists.txt конфигурировать проект командой config-web не нужно. Просто введите команду для сборки:
    Code
    1
    
    build-web
  • Обновите страницу браузера и вы увидите результат вывода текста в окне браузера:

Запуск веб-приложения на Android на локальном сервере



  • Обратите внимание, что локальный сервер http-server выводит адреса, например, у меня:
    Code
    1
    2
    3
    4
    5
    
    Available on:
      http://100.116.245.193:8080
      http://192.168.56.1:8080
      http://127.0.0.1:8080
    Hit CTRL-C to stop the server
  • Вы можете взять телефон, который подключён к Wi-Fi и ввести в его браузере адрес 192.168.56.1:8080 и приложение запустится на Android

Загрузка веб-приложения на бесплатный хостинг Vercel из консоли



  • Загрузите это веб-приложение на бесплатный хостинг Vercel по следующей инструкции: Установка Emscripten SDK (emsdk) и CMake (пролистайте до "Загрузка веб-приложения на бесплатный хостинг Vercel")

Миниатюра
Нажмите на изображение для увеличения
Название: 310386be29a8adbce84b534aac12b0c1bf1aedbe.png
Просмотров: 1831
Размер:	2.7 Кб
ID:	11471
Вложения
Тип файла: zip start-hello-ttf-wasm-sdl3-c.zip (3.0 Кб, 22 просмотров)
Тип файла: zip LiberationSans-Regular.zip (206.0 Кб, 21 просмотров)
Тип файла: zip SDL3-devel-3.4.0-wasm.zip (1.22 Мб, 67 просмотров)
Тип файла: zip SDL3_ttf-devel-3.2.2-wasm.zip (62.0 Кб, 96 просмотров)
Тип файла: zip freetype-2.13.3-wasm.zip (1.20 Мб, 97 просмотров)
Тип файла: zip finish-hello-ttf-wasm-sdl3-c.zip (211.0 Кб, 42 просмотров)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Новые блоги и статьи
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru