Three.jsでシェーダーを使ってみた

シェーダーを使ってアニメーション付きのかわいい3Dテキストを作ってみた。

サンプルページはこちら👈

シェーダーに取り掛かる前に、まず普通に3Dテキストを表示させた。

こんな感じにできた。フォントが丸っこくてかわいい。

色を設定する

フラグメントシェーダーで色を設定する。今回はNormal(法線)を使って色をつけてみた。頂点シェーダーからフラグメントシェーダーへ値を送信するため、使うのはvarying変数!

vertex.glsl
varying vec3 vPosition;
varying vec3 vNormal;

void main() {
  vec4 modelPosition = modelMatrix * vec4(position, 1.0);

  gl_Position = projectionMatrix * viewMatrix * modelPosition;

  vec4 modelNormal = modelMatrix * vec4(normal, 0.0);

  vPosition = modelPosition.xyz;
  vNormal = modelNormal.xyz;
}
fragment.glsl
varying vec3 vPosition;
varying vec3 vNormal;

void main() {
  gl_FragColor = vec4(vNormal.x, vNormal.y, 1.0 , 1.0);
}

可愛い色になった✨

外側を濃く、内側を薄くする

Normal(法線)と、カメラからオブジェクトへのベクトルがどの程度垂直なのかを調べて、垂直であるほど色が濃くなるようにしたい。ということでdot関数を使ってみる。

dot(x, y)はxとyの内積をfloatで返す

fragment.glsl
void main() {
  //フレネル
  vec3 viewDirection = normalize(vPosition - cameraPosition);
  float fresnel = dot(viewDirection, vNormal) + 1.0;
  fresnel = pow(fresnel, 2.0);
  fresnel *= 5.0;

  gl_FragColor = vec4(vNormal.x, vNormal.y, 1.0 , fresnel);
}

なかなかいい感じ✨

ギザギザのアニメーションをつける

経過時間を使って、3Dテキストの輪郭(?)がギザギザするようにした。sin()をいくつか組み合わせることで、アニメーションが一定じゃなくなることがポイント💡

このグラフ計算機を使うと便利👈

GLSLではランダムな数字を返す関数が存在してないぽいので、誰かが用意してくれている関数を使う。こちらをコピペしてきた。

vertex.glsl
uniform float uTime;

float random (vec2 st) {
  return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}

void main() {
  vec4 modelPosition = modelMatrix * vec4(position, 1.0);

  float glitchTime = uTime - modelPosition.y;
  float glitchStrength = sin(glitchTime) + sin(glitchTime * 3.45) +  sin(glitchTime * 8.76);
  glitchStrength /= 3.0;
  glitchStrength *= 0.07;
  modelPosition.x += (random(modelPosition.xz + uTime) - 0.5) * glitchStrength;
  modelPosition.z += (random(modelPosition.zx + uTime) - 0.5) * glitchStrength;

  gl_Position = projectionMatrix * viewMatrix * modelPosition;

  vec4 modelNormal = modelMatrix * vec4(normal, 0.0);

  vPosition = modelPosition.xyz;
  vNormal = modelNormal.xyz;
}

完成✨

もっと勉強して、複雑なアニメーションにも挑戦したい…!!