Babylon.js предоставляет возможность работы в
headless-режиме, то есть без привязки к DOM и
визуальному отображению на экране. Такой подход особенно полезен для
серверного рендеринга, генерации изображений,
тестирования сцен и вычислений, требующих GPU. Headless-контекст
создаётся с помощью WebGL OffscreenCanvas или
библиотек, эмулирующих WebGL в Node.js, таких как gl или
headless-gl.
Пример создания сцены в headless-режиме:
const { Engine } = require('@babylonjs/core/Engines/engine');
const { Scene } = require('@babylonjs/core/scene');
const createGLContext = require('gl');
const width = 800;
const height = 600;
const gl = createGLContext(width, height);
const engine = new Engine(gl, true, { preserveDrawingBuffer: true, stencil: true });
const scene = new Scene(engine);
Здесь ключевым моментом является передача контекста gl в
конструктор Engine. Это позволяет рендерить сцены
без использования HTML Canvas.
Для эффективного рендеринга на сервере важно учитывать несколько параметров Engine:
preserveDrawingBuffer — сохраняет
буфер после рендера, что позволяет считывать пиксели для дальнейшей
обработки или сохранения в изображение.stencil и depth —
включение этих буферов необходимо для корректной работы сложных
материалов, теней и постобработки.disableWebGL2Support — иногда нужно
принудительно использовать WebGL1 для совместимости с эмуляторами.Пример конфигурации:
const engine = new Engine(gl, true, {
preserveDrawingBuffer: true,
stencil: true,
disableWebGL2Support: false
});
Все объекты Babylon.js — Meshes, Cameras, Lights, Materials — работают в headless-сцене так же, как и в браузере. Разница только в том, что нет отображения на экране, поэтому визуальная проверка невозможна.
Для добавления базовых объектов:
const { ArcRotateCamera } = require('@babylonjs/core/Cameras/arcRotateCamera');
const { HemisphericLight } = require('@babylonjs/core/Lights/hemisphericLight');
const { Vector3 } = require('@babylonjs/core/Maths/math.vector');
const { MeshBuilder } = require('@babylonjs/core/Meshes/meshBuilder');
const camera = new ArcRotateCamera("camera", Math.PI / 2, Math.PI / 4, 10, Vector3.Zero(), scene);
const light = new HemisphericLight("light", new Vector3(0, 1, 0), scene);
const sphere = MeshBuilder.CreateSphere("sphere", { diameter: 2 }, scene);
Для получения изображения сцены из headless-Engine используется метод
engine.readPixels(), который возвращает
массив пикселей в формате RGBA. Дальше данные можно сохранять в PNG или
JPEG с помощью библиотек pngjs или
jpeg-js.
Пример:
const fs = require('fs');
const { PNG } = require('pngjs');
engine.runRenderLoop(() => {
scene.render();
const pixels = engine.readPixels(0, 0, width, height);
const png = new PNG({ width, height });
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const idx = (y * width + x) * 4;
const pngIdx = ((height - y - 1) * width + x) * 4;
png.data[pngIdx] = pixels[idx];
png.data[pngIdx + 1] = pixels[idx + 1];
png.data[pngIdx + 2] = pixels[idx + 2];
png.data[pngIdx + 3] = pixels[idx + 3];
}
}
png.pack().pipe(fs.createWriteStream('scene.png'));
});
Важно помнить, что оси Y инвертированы при считывании пикселей, поэтому строки нужно переворачивать.
Headless-контекст полностью поддерживает post-processes, PBR материалы, шейдеры и текстуры. Текстуры можно загружать из файлов или создавать программно:
const { Texture } = require('@babylonjs/core/Materials/Textures/texture');
const texture = new Texture("textures/wood.jpg", scene, false, false);
sphere.material = new StandardMaterial("mat", scene);
sphere.material.diffuseTexture = texture;
Для более сложной графики доступна GPU
постобработка, например Bloom, SSAO и FXAA. Все эффекты
работают, если Engine создается с
preserveDrawingBuffer: true и корректным
WebGL-контекстом.
Для массового рендеринга на сервере рекомендуется:
SceneLoader.ImportMeshAsync.Пример асинхронной загрузки:
const { SceneLoader } = require('@babylonjs/core/Loading/sceneLoader');
async function loadModel(scene) {
const result = await SceneLoader.ImportMeshAsync("", "models/", "house.babylon", scene);
return result.meshes;
}
При headless-рендеринге рекомендуется использовать меньшие
размеры текстур и оптимизированные форматы (.jpg,
.png). PBR материалы полностью
поддерживаются, но могут увеличивать время рендеринга, поэтому баланс
между качеством и производительностью критичен.
Для динамических текстур и renderTarget:
const { RenderTargetTexture } = require('@babylonjs/core/Materials/Textures/renderTargetTexture');
const rtt = new RenderTargetTexture("rtt", { width: 512, height: 512 }, scene);
sphere.material.diffuseTexture = rtt;
Headless Babylon.js подходит для:
Node.js-сервер может рендерить сотни сцен в фоне, используя очереди и пул WebGL контекстов.
Headless-Engine поддерживает WebGL2, но некоторые расширения GPU могут отсутствовать. В таком случае Engine автоматически падает на WebGL1. Следует учитывать:
Использование Babylon.js в headless-режиме открывает возможности серверного рендеринга и автоматической генерации графики без браузера. Правильная настройка Engine, оптимизация текстур, асинхронная загрузка ресурсов и корректная работа с пикселями позволяют создавать качественные изображения и сложные сцены полностью на сервере, сохраняя гибкость и функциональность библиотеки.