فصول الأدوات المساعدة لتقديم النص في ثلاثة. js باستخدام خطوط صورة نقطية و MSDF (حقول المسافة الموقعة متعددة القنوات).
متشوق من ثلاثة bmfont-text.
ويشمل:
للحصول على هذا العمل ، ستحتاج إلى بعض الملفات المحددة ، يمكنك إنشاءها باستخدام MSDF-BMFONT-XML أو مع الأداة عبر الإنترنت. يمكنك أيضًا التحقق من MSDF-font-fontory ، ويتضمن بالفعل بعض الملفات التي يمكنك استخدامها وبرنامج نصي لإنشاء ملفاتك بسهولة.
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 (Boolean): ما إذا كان الملمس سوف يكون y (صواب افتراضي)multipage (Boolean): ما إذا كان يجب بناء هذه الهندسة باستخدام معرفات صفحة إضافية تحتوي على صفحة. هذا ضروري للخطوط المتعددة النصية (خطأ افتراضي) font (المطلوب) تعريف BMFONT الذي يحمل chars ، kernings ، إلخtext (سلسلة) النص للتخطيط. سوف تتسبب الأحرف الجديدة ( n)width (الرقم ، اختياري) العرض المطلوب لمربع النص ، يتسبب في تغليف الكلمات والقطع في وضع "قبل". اتركه غير محدد لإزالة الالتفاف على الكلمات (السلوك الافتراضي)mode (سلسلة) وضع للكلمة. يمكن أن يكون "مسبقًا" (الحفاظ على التباعد) ، أو "Nowrap" (مسافة بيضاء ، ولكن لا تفتح سوى الأحرف الجديدة) ، على خلاف ذلك ، يفترض سلوك Word-Wrap الطبيعي (Mullapse WhiteSpace ، أو كسر في العرض أو الخطوط الجديدة)align (سلسلة)" يسار "أو" مركز "أو" يمين "(افتراضي: يسار)letterSpacing (رقم) تباعد الحروف بالبكسل (الافتراضي: 0)lineHeight (رقم) ارتفاع الخط بالبكسل (افتراضي إلى font.common.lineheight)tabSize (رقم) عدد المساحات المراد استخدامها في علامة تبويب واحدة (افتراضي 4)start (رقم) فهرس البدء في النص إلى التخطيط (الافتراضي 0)end (رقم) فهرس النهاية (حصري) في النص إلى التخطيط (Text.Length) update(options)إعادة بناء الهندسة باستخدام الخيارات المعطاة. أي خيارات غير محددة هنا سوف تتخلف عن تلك المحددة في المُنشئ. ستقوم هذه الطريقة بإعادة حساب تخطيط النص وإعادة بناء المخازن المؤقتة WebGL. يمكن أن تكون الخيارات كائنًا ، أو سلسلة - تعادل {text: str}.
layoutمثيل تخطيط النص ، يمكنك استخدامه للوصول إلى سمات التخطيط مثل:
العرض ، الطول ، السليل ، الصعود ، xheight ، خط الأساس ، capheight ، lineheight ، طبقة ، حرفي
visibleGlyphs مجموعة تم ترشيحها من geometry.layout.glyphs تهدف إلى التوافق مع بيانات Vertex المستخدمة من قبل Bufferattributes الأساسية.
هذه مجموعة من الكائنات { line, position, index, data } ، انظر هنا. على سبيل المثال ، يمكن استخدام هذا لإضافة bufferattribute جديدة لإزاحة line .
إلى جانب سمات الهندسة الأساسية. هناك بعض سمات النص المحددة ، في الغالب مفيدة لأغراض الرسوم المتحركة.
positionuv : إحداثيات الأشعة فوق البنفسجية المستخدمة لرسم خريطة الحرف الأيمن في رباعية الحرف الأيمنcenter : مركز كل حرف رباعيlayoutUv : إحداثيات الأشعة فوق البنفسجية للكتلة النصية الكاملة.glyphUv : إحداثيات الأشعة فوق البنفسجية لكل حرف فردي رباعي.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 مفيد لتقديم خطوط صغيرة ، سيقوم بتبديل حساب تقديم ألفا لجعلها أكثر سلاسة بصريًا
إذا كنت ترغب في إنشاء بعض التأثيرات النصية المحددة ، فيمكنك إنشاء رمز GLSL الخاص بك في مادة التظليل الخاصة بك استنادًا إلى ظلال MSDFTextMaterial.
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