three.js 文本_使用Three-bmfont-text在Three.js中创建文本

three.js 文本

three.js 文本

thumbnail

There are many ways of displaying text inside a Three.js application: drawing text to a canvas and use it as a texture, importing a 3D model of a text, creating text geometry, and using bitmap fonts — or BMFonts. This last one has a bunch of helpful properties on how to render text into a scene.

在Three.js应用程序内显示文本的方法有很多:将文本绘制到画布上并将其用作纹理,导入文本的3D模型,创建文本几何图形以及使用位图字体(或BMFonts)。 最后一个关于如何将文本渲染到场景中的一堆有用的属性。

Text in WebGL opens many possibilities to create amazing things on the web. A great example is Sorry, Not Sorry by awesome folks at Resn or this refraction experiment by Jesper Vos. Let’s use Three.js with three-bmfont-text to create text in 3D and give it a nice look using shaders.

WebGL中的文本为在网络上创建惊人的事物提供了许多可能性。 一个很好的例子是Resn的优秀人员对不起,而不是对不起,或者Jesper Vos进行的折射实验。 让我们将Three.js与three-bmfont-text一起使用,以3D格式创建文本,并使用着色器为其提供漂亮外观。

Three-bmfont-text is a tool created by Matt DesLauriers and Jam3 that renders BMFont files in Three.js, allowing to batch glyphs into a single geometry. It also supports things like word-wrapping, kerning, and msdf — please watch Zach Tellman’s talk on distance fields, he explains it very good.

Three-bmfont-text是由Matt DesLauriersJam3创建的工具,用于在Three.js中呈现BMFont文件,从而可以将字形批量化为单个几何体。 它还支持自动换行,字距调整和msdf等功能-请观看Zach Tellman在距离场上的演讲,他解释得很好。

With all that said, let’s begin.

综上所述,让我们开始吧。

Attention: This tutorial assumes you have some understanding of 注意:本教程假定您对 Three.js, GLSL shaders and Three.js ,GLSL着色器和 glslify, so we’ll skip things like glslify有所了解,因此我们将跳过诸如 how to set up a scene and import shaders. 设置场景和导入着色器之类的操作。

入门 (Getting started)

Before everything, we need to load a font file to create a geometry three-bmfont-text provides packed with bitmap glyphs. Then, we load a texture atlas of the font which is a collection of all characters inside a single image. After loading is done, we’ll pass the geometry and material to a function that will initialize a Three.js setup. To generate these files check out this repository.

在开始之前,我们需要加载一个字体文件来创建一个几何图形,三个bmfont-text提供了位图字形。 然后,我们加载字体的纹理图集,该纹理图集是单个图像内所有字符的集合。 加载完成后,我们会将几何图形和材质传递给一个函数,该函数将初始化Three.js设置。 要生成这些文件,请签出该存储库

const createGeometry = require('three-bmfont-text');
const loadFont = require('load-bmfont');

loadFont('fonts/Lato.fnt', (err, font) => {
  // Create a geometry of packed bitmap glyphs
  const geometry = createGeometry({
    font,
    text: 'OCEAN'
  });
  
  // Load texture containing font glyphs
  const loader = new THREE.TextureLoader();
  loader.load('fonts/Lato.png', (texture) => {
    // Start and animate renderer
    init(geometry, texture);
    animate();
  });
});

创建文本网格 (Creating the text mesh)

It’s time to create the mesh with the msdf shader three-bmfont-text comes with. This module has a default vertex and fragment shader that forms sharp text. We’ll change them later to produce a wavy effect.

是时候使用附带的msdf着色器创建3bmfont-text了。 该模块具有默认的顶点和片段着色器,可形成清晰的文本。 稍后我们将对其进行更改以产生波浪效果。

const MSDFShader = require('three-bmfont-text/shaders/msdf');

function init(geometry, texture) {
  // Create material with msdf shader from three-bmfont-text
  const material = new THREE.RawShaderMaterial(MSDFShader({
    map: texture,
    color: 0x000000, // We'll remove it later when defining the fragment shader
    side: THREE.DoubleSide,
    transparent: true,
    negate: false,
  }));

  // Create mesh of text       
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(-80, 0, 0); // Move according to text size
  mesh.rotation.set(Math.PI, 0, 0); // Spin to face correctly
  scene.add(mesh);
}

And now the text should appear on screen. Cool, right? You can zoom and rotate with the mouse to see how crisp the text is.

现在文本应该出现在屏幕上。 酷吧? 您可以使用鼠标缩放和旋转以查看文本的清晰度。

演示地址

Let’s make it more interesting in the next step.

让我们在下一步变得更有趣。

GLSL (GLSL)

顶点着色器 (Vertex shader)

To oscillate the text, trigonometry is our best friend. We want to make a sinusoidal movement along the Y and Z axis — up and down, inside and outside the screen. A vertex shader fits the bill for this since it handles the position of the vertices of the mesh. But before this, let’s add the shaders to the material and create a time uniform that will fuel them.

为了使文本振荡,三角函数是我们最好的朋友。 我们希望沿着Y和Z轴(在屏幕的内部和外部)上下进行正弦运动。 顶点着色器适合此目的,因为它可以处理网格顶点的位置。 但是在此之前,让我们将着色器添加到材质中,并创建一个将为其加油的时间均匀性。

function init(geometry, texture) {
  // Create material with msdf shader from three-bmfont-text
  const material = new THREE.RawShaderMaterial(MSDFShader({
    vertexShader,
    fragmentShader,
    map: texture,
    side: THREE.DoubleSide,
    transparent: true,
    negate: false,
  }));

  // Create time uniform from default uniforms object
  material.uniforms.time = { type: 'f', value: 0.0 };
}

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  // Update time uniform each frame
  mesh.material.uniforms.time.value = this.clock.getElapsedTime();
  mesh.material.uniformsNeedUpdate = true;

  renderer.render(scene, camera);
}

Then we’ll pass it to the vertex shader:

然后,将其传递给顶点着色器:

// Variable qualifiers that come with the msdf shader
attribute vec2 uv;
attribute vec4 position;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
varying vec2 vUv;
// We passed this one
uniform float time;

void main() {
  vUv = uv;

  vec3 p = vec3(position.x, position.y, position.z);

  float frequency1 = 0.035;
  float amplitude1 = 20.0;
  float frequency2 = 0.025;
  float amplitude2 = 70.0;

  // Oscillate vertices up/down
  p.y += (sin(p.x * frequency1 + time) * 0.5 + 0.5) * amplitude1;

  // Oscillate vertices inside/outside
  p.z += (sin(p.x * frequency2 + time) * 0.5 + 0.5) * amplitude2;

  gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
}

Frequency and amplitude are properties of a wave that determine their quantity and their “height”. Because we are using a sine wave to move the vertices, these properties can help control the behavior of the wave. I encourage you to tweak the values to observe different results.

频率和振幅是决定其数量和“高度”的波的属性。 因为我们使用正弦波移动顶点,所以这些属性可以帮助控制波的行为。 我鼓励您调整值以观察不同的结果。

Okay, so here is the tidal movement:

好的,这是潮汐运动:

演示地址

片段着色器(Fragment shader)

For the fragment shader, I thought about just interpolating between two shades of blue – a light and a dark one. Simple as that.

对于片段着色器,我考虑过仅在两种蓝色阴影之间进行插值-浅色和深色。 就那么简单。

The built-in GLSL function mix helps interpolating between two values. We can use it along with a cosine function mapped from 1 to 0, so it can go back and forth these values and change the color of the text — a value of 1 will give a dark blue and 0 a light blue, interpolating the colors between.

内置的GLSL函数混合有助于在两个值之间进行插值。 我们可以将其与从1到0映射的余弦函数一起使用,因此它可以来回移动这些值并更改文本的颜色-值1表示深蓝色,0表示浅蓝色,对颜色进行插值之间。

#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif

// Variable qualifiers that come with the shader
precision highp float;
uniform float opacity;
uniform vec3 color;
uniform sampler2D map;
varying vec2 vUv;
// We passed this one
uniform float time;

// HSL to RGB color conversion module
#pragma glslify: hsl2rgb = require(glsl-hsl2rgb)

float median(float r, float g, float b) {
  return max(min(r, g), min(max(r, g), b));
}

void main() {
  // This is the code that comes to produce msdf
  vec3 sample = texture2D(map, vUv).rgb;
  float sigDist = median(sample.r, sample.g, sample.b) - 0.5;
  float alpha = clamp(sigDist/fwidth(sigDist) + 0.5, 0.0, 1.0);

  // Colors
  vec3 lightBlue = hsl2rgb(202.0 / 360.0, 1.0, 0.5);
  vec3 navyBlue = hsl2rgb(238.0 / 360.0, 0.47, 0.31);

  // Goes from 1.0 to 0.0 and vice versa
  float t = cos(time) * 0.5 + 0.5;

  // Interpolate from light to navy blue
  vec3 newColor = mix(lightBlue, navyBlue, t);

  gl_FragColor = vec4(newColor, alpha * opacity);
  if (gl_FragColor.a < 0.0001) discard;
}

And here it is! The final result:

在这里! 最终结果:

演示地址

其他例子(Other examples)

There is plenty of stuff one can do with three-bmfont-text. You can make words fall:

三bmfont文本可以做很多事情。 您可以使单词掉落:

演示地址

Enter and leave:

进入并离开:

演示地址

Distortion:

失真:

演示地址

Water blend:

水混合:

演示地址

Or mess with noise:

或杂乱无章:

演示地址

I encourage you to explore more to create something that gets you excited, and please share it with me via twitter or email. You can reach me there, too if you got any questions, or comment below.

我鼓励您探索更多内容,以创建让您兴奋的东西,并通过Twitter电子邮件与我分享。 如果您有任何疑问或在下面发表评论,也可以在这里与我联系。

Hope you learned something new. Cheers!

希望你学到新东西。 干杯!

参考和鸣谢 (References and Credits)

翻译自: https://tympanus.net/codrops/2019/10/10/create-text-in-three-js-with-three-bmfont-text/

three.js 文本

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值