Signed Distance Field (SDF) — это метод представления шрифтов и графики, который позволяет масштабировать текст без потери качества и эффективно использовать эффекты рендеринга, такие как свечения, тени и искажения. В контексте A-Frame, SDF-шрифты дают возможность создавать высококачественные 3D-тексты с динамическим освещением и минимальной нагрузкой на GPU.
Принцип работы: SDF создаёт для каждого пикселя текстуры значение расстояния до ближайшего контура символа. Положительные значения означают нахождение пикселя вне глифa, отрицательные — внутри. При рендеринге используется шейдер, который интерпретирует эти расстояния и формирует чёткий контур независимо от масштаба.
Преимущества использования SDF:
Для генерации SDF-шрифтов требуется исходный файл в формате TTF или OTF. Необходимо учитывать:
Процесс можно разбить на несколько этапов:
opentype.js для разбора
TTF-файлов и получения глифов в виде векторных контуров.import opentype from 'opentype.js';
opentype.load('fonts/Roboto-Regular.ttf', function(err, font) {
if (err) {
console.error('Ошибка загрузки шрифта', err);
return;
}
// Шрифт загружен, можно генерировать SDF
});
tiny-sdf:import TinySDF from 'tiny-sdf';
const sdf = new TinySDF(64, 8, 3, 'bold', 'black'); // размер, padding, radius, стиль, цвет
const canvas = sdf.draw('A'); // генерируется SDF для символа 'A'
document.body.appendChild(canvas); // отображение для проверки
Параметры TinySDF:
size — размер символа в пикселях.padding — дополнительное пространство вокруг символа,
предотвращающее обрезку при масштабировании.radius — радиус размытия для сглаживания краёв.fontStyle, fontWeight,
fontFamily — настройки стиля.canvas для размещения символов в
сетке.const canvasAtlas = document.createElement('canvas');
const ctx = canvasAtlas.getContext('2d');
canvasAtlas.width = 512;
canvasAtlas.height = 512;
// Пример размещения глифов
ctx.drawImage(sdf.draw('A'), 0, 0);
ctx.drawImage(sdf.draw('B'), 64, 0);
A-Frame поддерживает использование текстур SDF через компонент
text с параметром font и шейдером
msdf:
<a-scene>
<a-entity text="value: Hello SDF; font: url(fonts/Roboto-msdf.json); shader: msdf; color: #FF0000; width: 4"></a-entity>
</a-scene>
Ключевые моменты:
font — путь к JSON-файлу атласа с UV-координатами
глифов.shader: msdf — использование шейдера для правильного
рендеринга SDF.width — ширина текста в сцене; масштабирование не
ухудшает качество.SDF позволяет применять визуальные эффекты:
Пример использования эффекта свечения в кастомном шейдере:
float distance = texture2D(u_texture, v_uv).r;
float alpha = smoothstep(0.5 - 0.02, 0.5 + 0.02, distance);
vec3 glowColor = vec3(1.0, 0.5, 0.0);
gl_FragColor = vec4(mix(glowColor, u_color.rgb, alpha), 1.0);
Для больших проектов рекомендуется автоматизировать:
Пример скрипта Node.js:
const fs = require('fs');
const TinySDF = require('tiny-sdf');
const opentype = require('opentype.js');
const font = opentype.loadSync('fonts/Roboto-Regular.ttf');
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const sdf = new TinySDF(64, 8, 3, 'normal', 'black');
characters.split('').forEach(char => {
const canvas = sdf.draw(char);
fs.writeFileSync(`sdf/${char}.png`, canvas.toBuffer());
});
padding или radius.SDF-шрифты в A-Frame позволяют создавать визуально богатые, масштабируемые и высокопроизводительные текстовые элементы, которые интегрируются в 3D-сцены без потери качества при любых трансформациях.