Для чего нужна данная статья? :
Создать простое WebAR-приложение, которое интегрирует 3D-объекты с использованием камеры и сенсоров через браузер.
Зачем Вам это уметь? :
- использовать для компиляции в WebAssembly, что позволит интегрировать код Rust, с JavaScript для WebAR. Rust будет отвечать за вычисления и обработку, а взаимодействие с камерой и отображение AR-объектов будет происходить через JavaScript и HTML.
Пример использования: Обработка данных с камеры (например, распознавание маркеров) на стороне Rust с последующей передачей данных в WebAR приложение для отображения.
- использовать WebGL через WebAssembly для рендеринга 3D-объектов, которые используются в AR. Для этого можно использовать библиотеку wgpu.
Пример использования: Визуализация интерактивных 3D-объектов в реальном времени с рендерингом на стороне клиента.
- использовать Rust совместно с JavaScript-библиотеками для WebAR, такими как three.js, A-Frame или AR.js. Rust через WebAssembly будет выполнять сложные вычисления, такие как обработка компьютерного зрения, а JavaScript и существующие библиотеки будут отвечать за интеграцию с камерой и рендеринг.
Пример использования: Использование Rust для улучшения производительности алгоритмов распознавания объектов в реальном времени, а JavaScript для взаимодействия с WebAR-фреймворками.
- для разработки производительных алгоритмов распознавания объектов и обработки изображений для AR. Такие задачи, как отслеживание объектов, анализ маркеров или распознавание жестов, могут быть обработаны на стороне клиента при помощи Rust.
Пример использования: Распознавание маркеров AR или объектов реального мира с использованием алгоритмов компьютерного зрения, написанных на Rust.
- для разработки серверной части WebAR приложений, где сервер будет отвечать за обработку данных AR, таких как генерация 3D-контента, хранение данных о сессиях или кэширование сложных 3D-моделей. В этом случае WebAR приложение может взаимодействовать с сервером на Rust через REST API или WebSockets.
Пример использования: Сервер на Rust, отвечающий за хранение и предоставление 3D-моделей в реальном времени или за обработку AR-сессий.
- для привязки AR-объектов к конкретным местам в реальном мире. Rust может обрабатывать данные с GPS-сенсоров, магнитометров или акселерометров и передавать их в WebAssembly приложение для отображения AR.
Пример использования: Создание геолокационных приложений дополненной реальности, где Rust обеспечивает высокоэффективную обработку данных и их интеграцию в WebAR интерфейс.
Пример: WebAR приложение с Rust и WebAssembly:
Шаги:
- Установка и настройка Rust для WebAssembly: Убедитесь, что у вас установлен инструмент wasm-pack:
cargo install wasm-pack - Создание проекта: Создадим проект с использованием WebAssembly и Yew:
cargo new --lib webar_example
cd webar_example - Редактирование Cargo.toml: Добавьте зависимости для yew, wasm-bindgen, и wgpu:
[dependencies] wasm-bindgen = "0.2" yew = { version = "0.20", features = ["wasm-bindgen"] }
wgpu = "0.12" futures = "0.3" web-sys = { version = "0.3", features = ["Window", "HtmlCanvasElement"] }
js-sys = "0.3" console_error_panic_hook = "0.1" - Реализация логики WebAR в Rust:Основная логика состоит из 3 частей:Используем yew для интерфейса.
Используем wasm-bindgen для взаимодействия с JavaScript и WebAssembly.
Используем wgpu для рендеринга 3D-графики.
1. src/lib.rs — Главный файл и точка входа
#[wasm_bindgen(start)]
pub fn wasm_start() -> Result<(), JsValue>
- Это аналог main() для WebAssembly.
- Выполняется автоматически при загрузке .wasm модуля.
- Здесь подключается console_error_panic_hook (чтобы паники выводились в консоль браузера) и логирование.
static GLOBAL_STATE: Lazy<Arc<RwLock<AppState>>> = ...
- Используется паттерн Singleton + thread-safe глобальное состояние.
- Lazy — инициализируется один раз при первом обращении.
- Arc<RwLock<...>> — позволяет безопасно читать/писать из разных потоков (включая Web Workers).
#[wasm_bindgen]
pub struct WebARApp;
- Это тонкий прокси, который экспортируется в JavaScript.
- Все вызовы из JS (initialize, process_frame, render) идут через него.
2. src/binding/api.rs — Реализация бизнес-логики
Здесь находится основная логика инициализации:
- Создаётся детектор маркеров (ArUcoSimdDetector)
- Создаётся пул рабочих потоков (CVWorkerPool)
- Создаётся WebGPU-рендерер
Важный момент:
let detector = Arc::new(ArUcoSimdDetector::new())
as Arc<dyn crate::core::MarkerDetector + Send + Sync>;
Мы приводим конкретный тип к type-erased trait object. Это позволяет в будущем легко подменять реализацию (ArUco → Neural Detector и т.д.) — Dependency Inversion Principle (D).
3. src/core/ — Сердце SOLID-архитектуры
core/mod.rs определяет главный трейт:
pub trait MarkerDetector: Send + Sync {
fn detect(&self, frame: &FrameData) -> Vec<DetectedMarker>;
fn update_intrinsics(&self, intrinsics: CameraIntrinsics);
fn reset(&self);
}
- &self вместо &mut self — потому что мы используем Arc. Mutability достигается через внутренние RwLock.
- Send + Sync — обязательно для использования в многопоточной среде и передачи между worker'ами.
core/types.rs содержит основные структуры данных (DetectedMarker, FrameData, CameraIntrinsics).
4. src/cv/detector/aruco_simd.rs — Компьютерное зрение
Самый "тяжёлый" и производительный модуль.
Что он делает:
- rgb_to_gray() — очень быстрая конверсия RGBA → Grayscale (используется в каждом кадре).
- detect() — основной метод, который:Принимает кадр
Конвертирует в grayscale
Ищет кандидатов (маркеры)
Возвращает список DetectedMarker с позой в 3D пространстве.
Пока реализация упрощённая (заглушки), но структура уже готова к внедрению настоящего SIMD + contour detection + sub-pixel refinement.
5. src/threading/worker_pool.rs — Многопоточность
pub struct CVWorkerPool {
pool: rayon::ThreadPool,
}
- Использует Rayon — высокоуровневую библиотеку для data parallelism.
- web_spin_lock фича позволяет Rayon работать в WebAssembly (где нет настоящих OS threads, но есть Web Workers + SharedArrayBuffer).
- Метод submit() отправляет задачу (CVTask) в пул потоков, не блокируя главный поток.
Это критично для WebAR: компьютерное зрение не должно блокировать UI и рендеринг.
6. Глобальное состояние и потокобезопасность
Всё приложение использует комбинацию:
- Arc<T> — shared ownership
- RwLock<T> — множественные читатели + один писатель
- parking_lot — более быстрая и wasm-friendly реализация RwLock
Это позволяет:
- Главному потоку читать состояние без блокировок
- Фоновым worker'ам безопасно выполнять тяжёлые вычисления
Как работает весь цикл (frame loop)
- JavaScript захватывает кадр с камеры (getUserMedia)
- Преобразует в RGBA Uint8Array → передаёт в Rust через process_frame(rgba, w, h)
- Rust кладёт задачу в CVWorkerPool
- В фоне (в worker thread) выполняется:Конверсия в grayscale
Детекция маркеров (ArUco)
Оценка позы (PnP) - Результаты (позиции маркеров) возвращаются в JS (пока через канал или SharedArrayBuffer — в текущей версии упрощённо)
- JS вызывает render(delta_time) → WebGPU рисует 3D-объекты поверх реального мира