Найти в Дзене
Один Rust не п...Rust

Rust и графика

t.me/oneRustnoqRust Для чего нужна данная статья? :
Создать мультиплатформенное графическое приложение с: Найти альтернативы для работы с графикой:
✅ Игровые движки (Bevy, Fyrox, Godot Rust)
✅ Низкоуровневые графические API (wgpu, Vulkano, OpenGL)
✅ 2D/3D-визуализация (wgpu, raqote, Skia, Cairo)
✅ GUI (egui, iced, slint, gtk-rs)
✅ Веб-графика (WebGPU, WebGL, Canvas API)
✅ Физика и игровые ECS (Rapier, Legion)
✅ Обработка изображений (image, resvg)
✅ GPGPU-вычисления (CUDA, OpenCL, wgpu-compute) Зачем Вам это уметь? : Константы COMPUTE_WIDTH/HEIGHT — размер текстуры для Mandelbrot (800×600). Пример:
Представьте, что вы учитесь предсказывать цену дома по его площади и количеству комнат. MLP берёт эти два числа, умножает их на веса (параметры), добавляет смещение, а затем применяет GELU, чтобы результат не был слишком большим или маленьким. Пример:
Вы даёте сети фотографию кошки, и она говорит, что это кошка — но не учится на этом примере.
Backend — это "движок", который выполняет все в
Оглавление
nicktretyakov1/graphicML | Gitverse
ML на RUST без заморочек

t.me/oneRustnoqRust

Для чего нужна данная статья? :
Создать
мультиплатформенное графическое приложение с:

  1. 3D-сценой на движке Bevy, Fyrox или Godot Rust.
  2. Физикой с Rapier и Legion ECS.
  3. Низкоуровневым рендерингом через wgpu, Vulkano, OpenGL.
  4. GUI-интерфейсом (egui, iced, gtk-rs, slint).
  5. Веб-версией (WebGPU, WebGL, Canvas API).
  6. Обработкой изображений (image, resvg).
  7. Вычислениями на GPU (CUDA, OpenCL, wgpu-compute).

Найти альтернативы для работы с графикой:
Игровые движки (Bevy, Fyrox, Godot Rust)
Низкоуровневые графические API (wgpu, Vulkano, OpenGL)
2D/3D-визуализация (wgpu, raqote, Skia, Cairo)
GUI (egui, iced, slint, gtk-rs)
Веб-графика (WebGPU, WebGL, Canvas API)
Физика и игровые ECS (Rapier, Legion)
Обработка изображений (image, resvg)
GPGPU-вычисления (CUDA, OpenCL, wgpu-compute)

Зачем Вам это уметь? :

1. 2D-графика

Библиотеки для рендеринга 2D-графики:

  • wgpu – безопасная и кроссплатформенная графическая абстракция на основе Vulkan, Metal, DX12 и OpenGL.
  • vulkano – безопасная обертка над Vulkan.
  • glow – безопасная обертка над OpenGL.
  • minifb – минималистичная библиотека для создания окон и рендеринга пикселей.
  • pixels – простой буфер пикселей поверх wgpu.
  • softbuffer – библиотека для прямого управления буфером кадра без GPU.

Библиотеки для 2D-отрисовки и векторной графики:

  • image – работа с растровыми изображениями.
  • resvg – отрисовка SVG.
  • raqote – рендеринг векторной графики в стиле Cairo.
  • skia-safe – биндинги для Google Skia.
  • cairo-rs – биндинги для Cairo.

2. 3D-графика

Графические движки:

  • Bevy – современный ECS-движок с поддержкой wgpu.
  • Fyrox – удобный 3D-движок с GUI-редактором.
  • Godot Rust – Rust-биндинги для Godot.
  • Macroquad – удобный движок без зависимостей.
  • Tetra – 2D-игровой движок с OpenGL.

Прямой доступ к графическим API:

  • wgpu – поддерживает Vulkan, DX12, Metal.
  • vulkano – безопасная работа с Vulkan.
  • ash – низкоуровневые биндинги к Vulkan.
  • glium – удобный слой над OpenGL.
  • glutin – создание окон с OpenGL.

3. GUI (Графический интерфейс пользователя)

Фреймворки на Rust:

  • egui – быстрый и удобный GUI на wgpu.
  • druid – декларативный GUI с поддержкой piet.
  • iced – вдохновлен Flutter.
  • slint – декларативный GUI в стиле Qt/QML.
  • orbtk – для Redox OS и не только.
  • fltk-rs – биндинги для FLTK.

Биндинги для классических GUI-фреймворков:

4. Графика для научных расчетов и визуализации данных

  • plotters – графики и диаграммы.
  • plotlib – аналог Matplotlib.
  • Vello – для сложной графики и анимации.

5. Web-графика (WebAssembly + Rust)

  • WebGPU (wgpu-rs) – WebGPU в браузере.
  • Canvas API – рендеринг в <canvas> через wasm-bindgen.
  • WebGL (gl-rs) – биндинги к WebGL.
  • Three-d – 3D-рендеринг на WebAssembly.

6. GameDev и физика

  • Rapier – физический движок 2D/3D.
  • NPhysics – физический движок.
  • Legion – ECS-фреймворк для игр.
  • hecs – еще один ECS-фреймворк.

7. Инструменты для работы с шейдерами

  • naga – транслятор шейдеров.
  • spirv-cross – работа с SPIR-V.
  • rust-gpu – написание шейдеров на Rust.

8. Графика с использованием GPU (GPGPU)

  • cuda-rs – работа с CUDA.
  • wgpu-compute – вычисления на GPU через WebGPU.
  • ocl – OpenCL в Rust.
  • rust-gpu – Rust для GPU.

Давайте создадим прорисовку куба на экране.

  • bevy::prelude::* — основной движок для 3D-сцены, ECS, рендеринга.
  • bevy_rapier3d — физика (Rapier).
  • burn::* — ML-фреймворк (autodiff для градиентов, NdArray-бэкенд).
  • rayon — параллелизм для генерации данных ML.
  • wgpu::* — низкоуровневый доступ к GPU для compute-шейдера Mandelbrot.
  • egui_plot — графики в GUI.
  • flume — безопасный канал для mapping буфера wgpu (без futures_intrusive).
  • ::core::fmt — обязательный импорт для derive(Module, Debug) в burn (no_std совместимость).

Константы COMPUTE_WIDTH/HEIGHT — размер текстуры для Mandelbrot (800×600).

  • Mlp — кастомная нейросеть (MLP с двумя линейными слоями + Gelu-активация). MLP (Multi-Layer Perceptron) — это простейший вид нейронной сети, где слои соединены последовательно. Здесь используется два линейных слоя (простые матричные умножения) и функция активации GELU (вариант ReLU, который лучше работает с современными моделями).

Пример:
Представьте, что вы учитесь предсказывать цену дома по его площади и количеству комнат. MLP берёт эти два числа, умножает их на веса (параметры), добавляет смещение, а затем применяет GELU, чтобы результат не был слишком большим или маленьким.

  • Только forward-пропуск.
    Зависит от абстракции Backend (можно переключить на wgpu для GPU-обучения).Forward-пропуск — это процесс, когда нейросеть получает входные данные и вычисляет выходные, не обучаясь. То есть, она просто "пропускает" данные через себя, не изменяя свои веса.

Пример:
Вы даёте сети фотографию кошки, и она говорит, что это кошка — но не учится на этом примере.


Backend — это "движок", который выполняет все вычисления. Здесь используется абстракция, позволяющая легко переключаться между CPU и GPU (например, с помощью библиотеки wgpu для ускорения на видеокарте).

Пример:
Представьте, что вы можете готовить еду на плите (CPU) или в микроволновке (GPU). Backend — это выбор, на чём готовить.

  • #[derive(Module, Debug)] — burn-макрос для автоматической сериализации/клонирования параметров. Это специальная команда для Rust, которая автоматически добавляет модели возможности:
  • Module — позволяет модели работать как часть нейросети (например, сохранять и загружать веса).
  • Debug — позволяет выводить информацию о модели для отладки.

Пример:
Как если бы у вас был конструктор Lego, и вы могли бы легко копировать или сохранять свои постройки.

MlpConfig — конфигурация модели (hidden = 64).Это настройки модели, где hidden = 64 означает, что в скрытом слое 64 нейрона. Чем больше это число, тем сложнее модель, но тем дольше она учится.

Пример:
Как если бы вы выбрали, сколько этажей будет в вашем доме: 64 — это средний размер.

MlManager — менеджер модели (NonSend ресурс, так как burn-модели не Sync из-за lazy инициализации параметров).MlManager — это "управляющий" моделью. Он не может быть передан между потоками (NonSend), потому что параметры модели инициализируются только при первом использовании (lazy), и это небезопасно для многопоточности.

Пример:
Как если бы у вас был личный помощник, который работает только в одном кабинете и не может одновременно быть в другом.

Генерация данных:

  • Многопоточность: rayon распараллеливает генерацию 400 точек sin(x).Rayon — это библиотека для языка Rust, которая помогает автоматически распределять работу между несколькими потоками (ядрами процессора).

Простыми словами: Представьте, что вам нужно нарисовать 400 точек на графике функции sin(x). Вместо того чтобы рисовать их по одной, вы нанимаете несколько художников, и каждый рисует свою часть точек одновременно. Так работа идёт быстрее.

Пример: Если у вас 4 ядра процессора, Rayon может разделить генерацию 400 точек на 4 части и выполнить их параллельно.

Тренировка:

  • Создаётся тензор x/y с .require_grad() (autodiff).Тензор — это многомерный массив (например, таблица чисел). Метод .require_grad() включает автоматическое дифференцирование (autodiff) для этого тензора.

Простыми словами: Представьте, что у вас есть лист бумаги с числами (тензор). Вы говорите компьютеру: "Следи, как эти числа меняются, чтобы потом можно было понять, как они влияют на результат".

Пример: Если вы учите модель предсказывать цену дома, тензор может содержать данные о площади, количестве комнат и т.д. .require_grad() позволяет модели понимать, как изменение каждого параметра влияет на итоговую цену.

  • Клонируется модель (burn поддерживает clone для параметров). Клонирование модели — это создание её точной копии с теми же параметрами.

Простыми словами: Представьте, что у вас есть рецепт торта. Вы делаете его копию, чтобы можно было экспериментировать с новым рецептом, не портя оригинал.

Пример: В машинном обучении иногда нужно запустить несколько экспериментов с одной и той же моделью, но с разными данными или параметрами. Клонирование позволяет это сделать.

  • Adam-оптимизатор, 300 эпох, MSE-loss.Это алгоритм, который помогает модели "учиться" — подстраивать свои параметры, чтобы делать более точные предсказания.

300 эпох: Эпоха — это один полный проход по всем обучающим данным. 300 эпох означает, что модель увидит все данные 300 раз.

MSE-loss: Mean Squared Error — это способ измерить, насколько модель ошибается. Чем меньше MSE, тем точнее модель.

Простыми словами: Представьте, что вы учитесь стрелять из лука. Adam-оптимизатор — это тренер, который подсказывает, как поправить прицел. 300 эпох — это 300 тренировок. MSE-loss — это среднее расстояние от стрелы до мишени.

  • Backward + step — автоматические градиенты (autodiff). Backward: Это шаг, на котором модель считает, как ошибка зависит от каждого параметра (градиенты).Step: Это шаг, на котором модель обновляет свои параметры, чтобы уменьшить ошибку.

Простыми словами: Представьте, что вы поднимаетесь на гору и хотите спуститься вниз. Backward — это когда вы смотрите, в каком направлении идти, чтобы спускаться быстрее. Step — это когда вы делаете шаг в этом направлении.

  • Результат сохраняется в y_pred для графика. y_pred — это предсказания модели, которые сохраняются для построения графика.

Простыми словами: После обучения модель предсказывает значения (например, y = sin(x)) и сохраняет их в переменную y_pred, чтобы потом можно было нарисовать график и сравнить с реальными данными.

3. GPGPU абстракция (ООП + SOLID + многопоточность)

WgpuComputeBackend — реализация на WGPU — это современный графический API (интерфейс программирования), который позволяет работать с графикой и вычислениями на GPU (видеокарте). Он похож на Vulkan или DirectX, но более универсален и работает на разных платформах.

Пример:
Представьте, что вы хотите нарисовать красивую картинку или сделать сложные расчёты. Вместо того чтобы загружать процессор (CPU), вы передаёте эту работу видеокарте (GPU), которая справляется с такими задачами гораздо быстрее.

  • Создаёт compute-шейдер (mandelbrot.wgsl — классический Mandelbrot на GPU). Compute-шейдер — это программа, которая выполняется на GPU и предназначена для вычислений, а не для рисования. Здесь используется шейдер, который рассчитывает множество Мандельброта (известный фрактал).

Пример:
Представьте, что у вас есть кухонный комбайн (GPU), который может очень быстро нарезать овощи (выполнять вычисления). Compute-шейдер — это рецепт, по которому комбайн работает.

  • Storage буфер для результата (RGBA8). Storage буфер — это область памяти на GPU, где хранятся данные, полученные после вычислений. RGBA8 означает, что каждый пиксель хранится как 4 байта: красный, зелёный, синий и альфа-канал (прозрачность).

Пример:
Представьте, что вы рисуете картину. Storage буфер — это холст, на котором хранятся все цвета и детали вашей картины.

  • Dispatch workgroups (8×8 = 64 threads per group). GPU делит работу на группы потоков (workgroups). Здесь каждая группа состоит из 8×8 = 64 потоков. Каждый поток выполняет часть вычислений.

Пример:
Представьте, что вы красите забор. Вместо того чтобы красить его одному, вы нанимаете 64 человека (потоков), каждый из которых красит свой кусочек. Работа идёт гораздо быстрее.

  • Staging буфер + map_async + flume-канал для безопасного чтения результата. Staging буфер — временная память, куда GPU копирует результаты, чтобы их можно было прочитать на CPU. map_async — асинхронное чтение данных из GPU, чтобы не блокировать основную программу. flume-канал — безопасный способ передачи данных между потоками в Rust.

Пример:
Представьте, что вы печёте пирог (GPU делает вычисления). Чтобы не обжечься, вы сначала кладёте его на поднос (staging буфер), потом аккуратно переносите на стол (map_async), и finally передаёте гостям через сервировку (flume-канал).

Многопоточность: Вычисление Mandelbrot запускается в отдельном std::thread::spawn (не блокирует Bevy-рендер). Вычисление Mandelbrot запускается в отдельном потоке, чтобы не блокировать основной рендер (отрисовку) в Bevy (игровом движке).

Пример:
Представьте, что вы готовите ужин и одновременно разговариваете по телефону. Вы не хотите, чтобы приготовление еды мешало разговору, поэтому делаете их параллельно.

4. Bevy приложение (ECS архитектура + интеграция всего)

main() — стандартный Bevy App — это игровой движок на языке Rust. DefaultPlugins — набор стандартных модулей (плагинов), которые добавляют базовую функциональность: окно, графику, обработку событий и т.д.
Пример:
Представьте, что вы строите дом. DefaultPlugins — это фундамент, стены и крыша, без которых дом не будет домом.

  • DefaultPlugins + WindowPlugin (1280×720). Плагин, который создаёт окно для вашего приложения с разрешением 1280 на 720 пикселей.
    Пример:
    Как экран телевизора: вы указываете, какой он будет по размеру.
  • EguiPlugin, RapierPhysicsPlugin + DebugRender. EguiPlugin — добавляет интерфейс (кнопки, графики, меню). RapierPhysicsPlugin — добавляет физику (гравитация, столкновения).
    Пример:
    Egui — как панель управления в игре (меню, кнопки).
    Rapier — как законы физики: если бросить мяч, он упадёт на пол.
  • insert_non_send_resource(MlManager::new()) — модель только в main thread. Создаётся ресурс MlManager (например, для машинного обучения), который работает только в основном потоке программы.
    Пример:
    Как если бы у вас был помощник, который может работать только в одной комнате (основной поток).
  • Startup системы: setup_scene, setup_compute_backends. Startup системы — функции, которые выполняются один раз при запуске программы. setup_scene — настраивает сцену (камера, свет, объекты). setup_compute_backends — настраивает вычислительные модули (например, для работы с графикой или данными).
    Пример:
    Как подготовка к спектаклю: расставляют декорации (setup_scene) и настраивают свет (setup_compute_backends).

  • Обычные системы: gui_system, update_compute_texture.

ComputeResources — ресурс для хранения бэкендов, текущего индекса, pending результата (Arc<Mutex<...>> для thread-safe) и текстуры. Ресурс для хранения данных, которые нужны для вычислений (например, текстуры, результаты вычислений).
Пример:
Как коробка с инструментами: там лежат всё, что нужно для работы (текстуры, результаты).

setup_compute_backends - Создаётся модуль для вычислений на GPU (видеокарте) с помощью библиотеки wgpu.
Пример:
Как если бы вы наняли суперкомпьютер для сложных расчётов, чтобы не нагружать основной компьютер.:

  • Берёт wgpu device/queue из Bevy рендера.
  • Создаёт WgpuComputeBackend.
  • Создаёт дефолтную текстуру (серый фон).

setup_scene - SVG (векторное изображение) → Pixmap (растровое изображение) → текстура для объектов в Bevy.
Пример:
Как если бы вы нарисовали картинку на бумаге (SVG), отсканировали её (Pixmap) и наклеили на куб в игре (Bevy Image).:

  • Камера, свет.
  • SVG → Pixmap → Bevy Image (текстура для кубов).
  • 5 динамических кубов с физикой (падают на пол).
  • Пол (fixed).
  • Плоскость для Mandelbrot (unlit материал с динамической текстурой).

gui_system (egui):

  • Кнопка "Обучить MLP" → ml.train() (в main thread).
  • Если trained — график sin(x) vs предсказание (egui_plot).
  • ComboBox для выбора бэкенда (пока только wgpu).
  • Кнопка "Вычислить Mandelbrot" → spawn thread с compute_mandelbrot → результат в pending.

update_compute_texture - Обновляет текстуру (картинку) на объекте, если есть новые данные.
Пример:
Как если бы вы рисовали картину и периодически добавляли новые детали.

Запускается отдельный поток для вычисления фрактала Мандельброта (сложная математическая картинка).
Пример:
Как если бы вы наняли отдельного художника, чтобы он нарисовал сложную картину, пока вы занимаетесь другими делами.

  • Берёт pending результат, обновляет .data текстуры (Bevy поддерживает динамическое обновление).

5. Как всё работает вместе (поток выполнения)

  1. Запуск: Bevy создаёт окно, инициализирует физику, рендер, egui.
  2. Startup: Сцена (кубы падают), compute backend, дефолтная текстура.
  3. Каждый кадр:Физика обновляется (Rapier).
    egui рисует окно.
    Если нажата кнопка ML — тренировка (300 эпох ~0.1-0.5 сек на CPU).
    График обновляется.
    Если нажата кнопка Mandelbrot — отдельный поток вычисляет на GPU (быстро), результат копируется в текстуру → плоскость показывает фрактал.
  4. Многопоточность: Rayon для данных ML, thread для GPGPU — рендер/UI не фризится.