今回は、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系の表現も増えてきているので、身につけていきたいですね。
最後まで読んでいただき、ありがとうございました!