• HOME
  • [Three.js]ShaderMaterialを使った色のMixについて
TomoyaOkada

[Three.js]ShaderMaterialを使った色のMixについて

記事をシェアする

今回は、Three.jsのShaderMaterialを使って2つの色をmixする方法についてご紹介します。

前提知識

・Three.jsを使ってオブジェクトの描画方法を知っている
・基本的なJavaScriptの記述方法を知っている


PlaneGeometryを設置する

まずは通常のマテリアルを使って表示をしていきます。

    const size = {
      x: 1.3,
      y: 1.3,
    };

    this.geometry = new PlaneGeometry(size.x, size.y);
    this.material = new MeshNormalMaterial();
    this.mesh = new Mesh(this.geometry, this.material);
    this.stage.scene.add(this.mesh);


MeshNormalMaterialにしているの以下のような見た目になっていると思います。



ここからShaderMaterialに変更して2色をmixしていこうと思います。


ShaderMaterialに変更

this.material = new MeshNormalMaterial();

  this.material = new ShaderMaterial({
      uniforms: {
        uTime: {
          value: 0.0,
        },
      },
      vertexShader: vertexShader,
      fragmentShader: fragmentShader,
    });


注意点としては、vertexShaderとfragmentShaderの記述は別ファイル管理にしている点です。

import vertexShader from "../shader/vertex.glsl?raw";
import fragmentShader from "../shader/fragment.glsl?raw";


別ファイルに分ける方法がわからない方は以下のようにしてもOKです。

   this.material = new ShaderMaterial({
      uniforms: {
        uTime: {
          value: 0.0,
        },
      },
      vertexShader: `
       //ここに書く
      `,
      fragmentShader: `
     //ここに書く
     `,
          });



vertexShaderの設定

今回は頂点をいじることはないので、スタンダードな記述のみになります。

varying vec2 vUv;
void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}



fragmentShaderの設定

本記事のメインとなる箇所です。

precision mediump float;
uniform float uTime;
varying vec2 vUv;

void main() {
    vec2 p = vUv;
    float direction = 0.5;
    
    vec3 colorFirst = vec3(0.318, 0.973, 0.934);
    vec3 colorSecond = vec3(0.973, 0.973, 0.318);
    vec3 finalColor = mix(colorFirst,colorSecond,direction);

    gl_FragColor = vec4(finalColor, 1.0);
}


colorFirstとcolorSecondをmix関数を使って、合わせています。
directionの値が0.0 = colorFirst、1.0 = colorSecondに変化します。

※0.0の時


※1.0の時


以上で2色のmixが完了しました。
次は少しアクセントを加えたものを見ていきましょう。


おまけ(step関数)

step関数というものがあるので追加してみましょう。

step関数

step(a, x)aはしきい値、xはチェックされる値。しきい値未満の場合は0.0を、それ以上の場合は1.0の二値化を行う関数

引用元

以下のように追加してみましょう。

float direction = 0.0;
direction = step(p.x,p.y);



成功していれば、添付のような表示になっていると思います。



おまけ(ノイズ)

ちょっとしたノイズを追加してみましょう。
いくつか追記がある為、それぞれ追加してください。

◼︎fragmentShader

precision mediump float;
uniform float uTime;
varying vec2 vUv;

float rand(vec2 n) { 
    return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}

float noise(vec2 p){
    vec2 ip = floor(p);
    vec2 u = fract(p);
    u = u*u*(3.0-2.0*u);
    
    float res = mix(
        mix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x),
        mix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),u.y);
    return res*res;
}


void main() {
    vec2 p = vUv;
    float strength = 5.0;
    float direction = noise(p+uTime) * p.x;
    
    vec3 colorFirst = vec3(0.318, 0.973, 0.934);
    vec3 colorSecond = vec3(0.973, 0.973, 0.318);

    vec3 finalColor = mix(colorFirst,colorSecond,direction*strength);

    gl_FragColor = vec4(finalColor, 1.0);
}


◼︎JavaScript

  onUpdate() {
    this.material.uniforms.uTime.value += 0.01;
  }


するとGif画像のような動きになっている事が確認できると思います。



ノイズを使った表現は数多くみられるので、この辺りはマスターしていきたい部分ですね。


本記事のまとめ

今回は、Three.jsのShaderMaterialを使って2色をmixする方法と追加の加工方法についてご紹介しました。
昨今のWebサイトには3D系の表現も増えてきているので、身につけていきたいですね。
最後まで読んでいただき、ありがとうございました!

記事をシェアする