three msdf text utils
1.0.0
使用位圖字體和MSDF(多通道簽名的距離字段)中的三個.j渲染文本渲染的實用程序類。
從三bmfont-Text分叉。
它包括:
為了獲得此工作,您需要一些特定的文件,可以使用MSDF-BMFONT-XML或在線工俱生成它們。您還可以檢查我的MSDF-FONT-FARTORY,它已經包含了一些您可以使用的文件和一個可以輕鬆生成文件的腳本。
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 ) ;選項可以是一個對象,也可以是字符串 - 等效於{text:str}。
flipY (布爾值):紋理是否會被y-flipper(默認為true)multipage (布爾值):是否使用包含頁面ID的額外緩衝區構建此幾何形狀。這對於多文本字體是必需的(默認為false) font (必需)具有字符,Kernings等的BMFONT定義text (字符串)要佈局的文本。 Newline字符( n)將導致銷售折斷width (數字,可選)文本框的所需寬度會導致單詞包裝和剪輯在“ pre”模式下。離開時不確定以刪除文字包裹(默認行為)mode (字符串)Word-wrapper的模式;可以是“ pre”(維持間距)或“ nowrap”(崩潰的空格崩潰,但僅在新線字符上斷開),否則假定正常的單詞包含行為(塌陷,空格崩潰,寬度或newlines)align (字符串)可以“左”,“中心”或“右”(默認:左)letterSpacing (編號)像素中的字母間距(默認:0)lineHeight (編號)像素中的線高(默認為font.common.lineheight)tabSize (編號)在單個選項卡中使用的空間數(默認4)start (編號)開始文本的啟動索引要進行佈局(默認為0)end (number)在文本中的結尾索引(獨家)到佈局(默認text.length) update(options)使用給定選項重新構建幾何形狀。此處未指定的任何選項默認為構造函數中的設置。此方法將重新計算文本佈局並重建WebGL緩衝區。選項可以是一個對象,也可以是字符串 - 等效於{text:str}。
layout文本佈局實例,您可以使用它來訪問佈局屬性,例如:
寬度,高度,下降,升天,Xheight,基線,傾斜度,lineHeight,Linestotal,Letterstotal
visibleGlyphs從geometry.layout.glyphs的過濾集,旨在與基礎bufferattributes使用的頂點數據對齊。
這是{ line, position, index, data }對象的數組,請參見此處。例如,這可以用來添加新的BufferAttribute以進行line偏移。
除了基本的幾何屬性。有一些特定文本的屬性,主要用於動畫目的。
positionuv :用於繪製正確字母的紫外線坐標center :每個字母四邊形的中心layoutUv :全文塊的紫外線坐標。glyphUv :每個字母Quad的紫外線坐標。glyphResolution :分辨每個單獨的字母四邊形。lineIndex :每行的索引lineLettersTotal :每行的總字母總量lineLetterIndex :每條字母的索引lineWordsTotal :按行的總單詞總量lineWordIndex :每個單詞的索引wordIndex :每個單詞的索引letterIndex :每個字母的索引它延伸到三個。
您可以通過從字體設置Atlas紋理來使用它:
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 ,
} ;注意: IS_SMALL boolean對於渲染小字體很有用,它將切換alpha渲染計算以使它們在視覺上更加順暢
如果您想制定一些特定的文本效果,則可以根據MSDFTEXTMATERIAL PANDER在著色器材料中創建自己的GLSL代碼。
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