Kelas utilitas untuk rendering teks dalam tiga.js menggunakan font bitmap dan msdf (bidang jarak yang ditandatangani multi-channel).
Dipotret dari Tiga-BMFont-Text.
Itu termasuk:
Untuk membuatnya berfungsi, Anda akan memerlukan beberapa file tertentu, Anda dapat menghasilkannya dengan MSDF-BMFont-XML atau dengan alat online. Anda juga dapat memeriksa factory msdf-font saya sudah menyertakan beberapa file yang dapat Anda gunakan dan skrip untuk menghasilkan file Anda dengan mudah.
npm install three-msdf-text-utils import { MSDFTextGeometry , MSDFTextMaterial } from "three-msdf-text-utils" ;
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js' ;
import * as THREE from 'three' ;
Promise . all ( [
loadFontAtlas ( "./fonts/roboto/roboto-regular.png" ) ,
loadFont ( "./fonts/roboto/roboto-regular.fnt" ) ,
] ) . then ( ( [ atlas , font ] ) => {
const geometry = new MSDFTextGeometry ( {
text : "Hello World" ,
font : font . data ,
} ) ;
const material = new MSDFTextMaterial ( ) ;
material . uniforms . uMap . value = atlas ;
const mesh = new THREE . Mesh ( geometry , material ) ;
} ) ;
function loadFontAtlas ( path ) {
const promise = new Promise ( ( resolve , reject ) => {
const loader = new THREE . TextureLoader ( ) ;
loader . load ( path , resolve ) ;
} ) ;
return promise ;
}
function loadFont ( path ) {
const promise = new Promise ( ( resolve , reject ) => {
const loader = new FontLoader ( ) ;
loader . load ( path , resolve ) ;
} ) ;
return promise ;
} const geometry = new MSDFTextGeometry ( options ) ;Opsi dapat berupa objek, atau string - setara dengan {text: str}.
flipY (Boolean): Apakah teksturnya akan diflip (default true)multipage (Boolean): Apakah akan membangun geometri ini dengan buffer tambahan yang berisi ID halaman. Ini diperlukan untuk font multi-tekstur (default false) font (wajib) Definisi BMFont yang memiliki karakter, kerning, dlltext (String) Teks ke tata letak. Karakter baru ( n) akan menyebabkan garis istirahatwidth (angka, opsional) Lebar yang diinginkan dari kotak teks, menyebabkan pembungkus kata dan kliping dalam mode "pra". Tinggalkan tidak terdefinisi untuk menghapus pembungkus kata (perilaku default)mode (string) mode untuk word-wrapper; dapat menjadi 'pra' (mempertahankan jarak), atau 'nowrap' (runtuhnya whitespace tetapi hanya memecah karakter baru), jika tidak mengasumsikan perilaku kata-kata yang normal (runtuhnya whitespace, pecah pada lebar atau telepon baru)align (string) dapat "kiri", "tengah" atau "kanan" (default: kiri)letterSpacing (Nomor) Jarak huruf dalam piksel (default: 0)lineHeight (angka) Tinggi garis dalam piksel (default ke font.common.lineHeight)tabSize (Nomor) Jumlah spasi yang akan digunakan dalam satu tab (default 4)start (Number) Indeks Mulai ke Teks ke Tata Letak (Default 0)end (angka) indeks akhir (eksklusif) ke dalam teks ke tata letak (teks default.length) update(options)Membangun kembali geometri menggunakan opsi yang diberikan. Opsi apa pun yang tidak ditentukan di sini akan default untuk yang ditetapkan dalam konstruktor. Metode ini akan menghitung ulang tata letak teks dan membangun kembali buffer WebGL. Opsi dapat berupa objek, atau string - setara dengan {text: str}.
layoutTeks Tata Letak Teks, Anda dapat menggunakannya untuk mengakses atribut tata letak seperti:
Lebar, Tinggi, Descender, Ascender, Xheight, Baseline, Capheight, Lineheight, Linestotal, Letterstotal
visibleGlyphs Set yang difilter dari geometry.layout.glyphs dimaksudkan untuk menyelaraskan dengan data simpul yang digunakan oleh buferattribut yang mendasarinya.
Ini adalah array objek { line, position, index, data } , lihat di sini. Misalnya, ini dapat digunakan untuk menambahkan bufferattribute baru untuk line offset.
Selain atribut geometri dasar. Ada beberapa atribut khusus teks, sebagian besar berguna untuk tujuan animasi.
positionuv : Koordinat UV yang digunakan untuk memetakan huruf yang tepat di huruf kanan quadcenter : Pusat Setiap Huruf QuadlayoutUv : Koordinat UV dari blok teks lengkap.glyphUv : Koordinat UV dari setiap quad huruf individu.glyphResolution : Resolusi masing -masing quad huruf individu.lineIndex : Indeks setiap barislineLettersTotal : Jumlah total huruf di setiap barislineLetterIndex : Indeks setiap huruf demi barislineWordsTotal : Jumlah total kata demi barislineWordIndex : Indeks setiap kata demi bariswordIndex : Indeks setiap kataletterIndex : Indeks setiap hurufItu meluas dari tiga.js shadermaterial
Anda dapat menggunakannya hanya dengan mengatur tekstur Atlas dari font Anda:
const material = new MSDFTextMaterial ( options ) ;
material . uniforms . uMap . value = atlas ; const defaultOptions = {
side : THREE . FrontSide ,
transparent : true ,
defines : {
IS_SMALL : false ,
} ,
extensions : {
derivatives : true ,
} ,
uniforms : {
// Common
uOpacity : { value : 1 } ,
uColor : { value : new Color ( "#ffffff" ) } ,
uMap : { value : null } ,
// Rendering
uThreshold : { value : 0.05 } ,
uAlphaTest : { value : 0.01 } ,
// Strokes
uStrokeColor : { value : new Color ( "#ff0000" ) } ,
uStrokeOutsetWidth : { value : 0.0 } ,
uStrokeInsetWidth : { value : 0.3 } ,
} ,
vertexShader ,
fragmentShader ,
} ; CATATAN: IS_SMALL BOOLEAN berguna untuk membuat font kecil, itu akan mengganti perhitungan render alfa untuk membuatnya secara visual jauh lebih halus
Jika Anda ingin membuat beberapa efek teks tertentu, Anda dapat membuat kode GLSL sendiri di materi shader Anda berdasarkan msdftextmaterial shader.
import { uniforms } from "three-msdf-text-utils" ;
import * as THREE from 'three' ;
const material = new THREE . ShaderMaterial ( {
side : DoubleSide ,
transparent : true ,
defines : {
IS_SMALL : false ,
} ,
extensions : {
derivatives : true ,
} ,
uniforms : {
// Common
... uniforms . common ,
// Rendering
... uniforms . rendering ,
// Strokes
... uniforms . strokes ,
} ,
vertexShader : `
// Attribute
attribute vec2 layoutUv;
attribute float lineIndex;
attribute float lineLettersTotal;
attribute float lineLetterIndex;
attribute float lineWordsTotal;
attribute float lineWordIndex;
attribute float wordIndex;
attribute float letterIndex;
// Varyings
varying vec2 vUv;
varying vec2 vLayoutUv;
varying vec3 vViewPosition;
varying vec3 vNormal;
varying float vLineIndex;
varying float vLineLettersTotal;
varying float vLineLetterIndex;
varying float vLineWordsTotal;
varying float vLineWordIndex;
varying float vWordIndex;
varying float vLetterIndex;
void main() {
// Output
vec4 mvPosition = vec4(position, 1.0);
mvPosition = modelViewMatrix * mvPosition;
gl_Position = projectionMatrix * mvPosition;
// Varyings
vUv = uv;
vLayoutUv = layoutUv;
vViewPosition = -mvPosition.xyz;
vNormal = normal;
vLineIndex = lineIndex;
vLineLettersTotal = lineLettersTotal;
vLineLetterIndex = lineLetterIndex;
vLineWordsTotal = lineWordsTotal;
vLineWordIndex = lineWordIndex;
vWordIndex = wordIndex;
vLetterIndex = letterIndex;
}
` ,
fragmentShader : `
// Varyings
varying vec2 vUv;
// Uniforms: Common
uniform float uOpacity;
uniform float uThreshold;
uniform float uAlphaTest;
uniform vec3 uColor;
uniform sampler2D uMap;
// Uniforms: Strokes
uniform vec3 uStrokeColor;
uniform float uStrokeOutsetWidth;
uniform float uStrokeInsetWidth;
// Utils: Median
float median(float r, float g, float b) {
return max(min(r, g), min(max(r, g), b));
}
void main() {
// Common
// Texture sample
vec3 s = texture2D(uMap, vUv).rgb;
// Signed distance
float sigDist = median(s.r, s.g, s.b) - 0.5;
float afwidth = 1.4142135623730951 / 2.0;
#ifdef IS_SMALL
float alpha = smoothstep(uThreshold - afwidth, uThreshold + afwidth, sigDist);
#else
float alpha = clamp(sigDist / fwidth(sigDist) + 0.5, 0.0, 1.0);
#endif
// Strokes
// Outset
float sigDistOutset = sigDist + uStrokeOutsetWidth * 0.5;
// Inset
float sigDistInset = sigDist - uStrokeInsetWidth * 0.5;
#ifdef IS_SMALL
float outset = smoothstep(uThreshold - afwidth, uThreshold + afwidth, sigDistOutset);
float inset = 1.0 - smoothstep(uThreshold - afwidth, uThreshold + afwidth, sigDistInset);
#else
float outset = clamp(sigDistOutset / fwidth(sigDistOutset) + 0.5, 0.0, 1.0);
float inset = 1.0 - clamp(sigDistInset / fwidth(sigDistInset) + 0.5, 0.0, 1.0);
#endif
// Border
float border = outset * inset;
// Alpha Test
if (alpha < uAlphaTest) discard;
// Output: Common
vec4 filledFragColor = vec4(uColor, uOpacity * alpha);
// Output: Strokes
vec4 strokedFragColor = vec4(uStrokeColor, uOpacity * border);
gl_FragColor = filledFragColor;
}
` ,
} ) ;
material . uniforms . uMap . value = atlas ; npm installnpm run dev