Shader Cubicle

TwitterGitHub
Tweet

線形補間を用いたグラデーションの実装

  • フラグメントシェーダー

前回の記事「グラデーションの実装」ではThree.jsのUV座標を使用してグラデーションを実装した。

varying vec2 vUv;

void main () {
  float red =  vUv.x;
  gl_FragColor = vec4(red, 0.0, 0.0, 1.0);
}

上記では黒から赤へのグラデーションであったが、今回は線形補間を利用して2色以上のグラデーションを実装してみる。

線形補間に関しては「正規化・線形補間・マップ|クリエイティブコーディングの教科書」をみるとわかりやすい。

ついでに本記事でもざっくりと説明してみる。点aと点bがある時に、この2点を結ぶことを補間というわけだか、くわえて結んだ線が直線の時を線形補間という。この時の線分abは一次関数で表すことが可能だが(線形補間は1次補間とも呼ばれる)、GLSLにおいてはmixを使うことで表現できる。

mix(a, b, t)は、線分ab上をt : 1 - tに内分する点Tの位置を計算してくれることとなる。たとえば点aを(0, 0)、点bを(4, 8)とすれば以下のようになる。

点a = (0, 0)
点b = (4, 8) とする

// t = 0 の時
mix(a, b, 0) = (0, 0)

// t = 0.25 の時
mix(a, b, 0.25) = (1, 2)

// t = 0.5 の時
mix(a, b, 1) = (2, 4)

// t = 1 の時
mix(a, b, 1) = (4, 8)

2色の線形補間

上記を踏まえてから、赤から青に変化するグラデーションを実装してみる。

fragmentShader

3色の線形補間

次に赤から緑、緑から青になるように実装してみる。

fragmentShader

上記のコードはざっくり以下のような感じである。

// 赤、緑、青のvec3型の配列を宣言
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 blue = vec3(0.0, 0.0, 1.0);
vec3[3] rgb = vec3[](
  red, green, blue
);

// [0 ~ 1]を[0 ~ 2]に変換する
float doubleUv = vUv.x * 2.0;

// 配列のindexはint型である必要がある
int index = doubleUv < 1.0 ? 0 : 1;

// doubleUvが[0 ~ 2]なのでfractは0以上1未満を2回繰り返す
// →赤から緑、緑から赤
vec3 mixed = mix(rgb[index], rgb[index+1], fract(doubleUv));
//...

4色のバイリニア補間(双線形補間)

最後に上下左右の4色でグラデーションするためにバイリニア補間(双線形補間)というものを使ってみる。

fragmentShader

バイリニア補間についてはあまり理解しきれていないので、本記事では詳しく触れないが(かわり参考を載せておく)、以下のようなコードを書いている。

// 4色の宣言
vec3 red = vec3(1.0, 0.0, 0.0);
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 blue = vec3(0.0, 0.0, 1.0);
vec3 yellow = vec3(1.0, 1.0, 0.0);

// 上半分でx軸方向に線形補間(赤→緑)
vec3 mixedTop = mix(red, green, vUv.x);

// 上半分でx軸方向に線形補間(青→黄色)
vec3 mixedBottom = mix(blue, yellow, vUv.x);

// y軸方向にmixedTopとmixedBottomを線形補間
// y軸は下が0で上が1となることに気をつける
vec3 mixed = mix(mixedBottom, mixedTop, vUv.y);

参考

前の記事へ