regl入門

f:id:suzu_kun:20181217172535p:plain

こんにちは、カヤック・クライアントワークチーム・フロントエンドエンジニアのMr.ブラウンです。
今回は、
Fast functional WebGL
と謳っているreglを紹介いたします。
※ 多少、WebGL・GLSLをさわったことがある前提で話が進んでいきます。


はじめに

reglは、シェーダーを自分で書く必要があります。
three.jsのようにBoxGeometryというクラスを使えば簡単に立方体をつくることができたり、
PixiJSのようにGraphicsというクラスを使えば簡単に四角形などをつくることができたり…
はできません。
四角形であろうと、丸であろうと、立方体であろうと、
簡単に図形をつくることができるクラスやメソッドは用意されておらず、
reglで何かをつくりたければ自分自身でシェーダーを書かなければいけません。
(three.jsPixiJSはメジャーなcanvas系のライブラリです)

(ライブラリについての記事はこちら) techblog.kayac.com

では、他のライブラリと比べて嬉しい点はどこかと言うと、

  • 関数型っぽく書ける
  • パッと見、簡単・お手軽そうに見えるので心に優しい

(コードの量が少なく・必要なものを引数で渡すだけ…パッと見、簡単そうに見えませんか?)

regl({
    // バーテックスシェーダー
    vert: `
        attribute vec3 a_position;

        void main() {
            gl_Position = vec4(a_position, 1.0);
        }
    `,
    // フラグメントシェーダー
    frag: `
        precision mediump float;
        
        uniform vec4 u_color;
        
        void main() {
            gl_FragColor = u_color;
        }
    `,
    // attribute修飾子付き変数
    attributes: {
        a_position: [
            [0, 0.5, 0],
            [0.25, -0.25, 0],
            [-0.25, -0.25, 0],
        ],
    },
    // uniform修飾子付き変数
    uniforms: {
        u_color: [1.0, 0.5, 0.0, 1.0],
    },
    // 頂点の数
    count: 3,
})();

とくに、「関数型っぽく書ける」という部分がオススメポイントなのですが…
僕は今でも思っています、「つまりどういうことだ…」と。

正直、僕は簡単そうに見える見た目に惑わされて入門しました。
関数型プログラミング言語もさわったことがありません。

そのため、「reglはこうやって使うと強い!」という方法は紹介できないのですが、
「関数型っぽく書ける」という点は、「強そう!」と思いましたので
reglを知ってもらうために、この記事を書いています。
そして、ハマった方から「reglの使い方を教えてもらおう!」と企んでいます。

準備

まずは、reglを入手しましょう。
この記事で使用しているreglのversionは、1.3.9です。

npmの方はこちら

npm install -D regl

cdnの方はこちら

<script src="//npmcdn.com/regl/dist/regl.min.js"></script>

公式ドキュメント

まずはここから

オレンジ色の三角形をつくってみましょう。

f:id:suzu_kun:20181218094556p:plain

ステップ 1 "canvasの入れ物を用意する"

canvasの入れ物を用意します。
ここの説明はこれだけになります。

<div class="view"></div>
const $view = document.querySelector('.view');

ステップ 2 "createREGLを実行して、reglインスタンスをつくる"

reglを始めるには、 createREGLという関数を実行し、reglインスタンスをつくる必要があります。
このインスタンスに、このあと出てくる描画関数をつくるための関数などが詰まっています。

createREGLは、reglインスタンスを返すだけでなく、
containerプロパティに入れたDOMに、canvasを追加してくれます。

// npmの方だけ
import createREGL from 'regl';

const regl = createREGL({
    container: $view,
    pixelRatio: window.devicePixelRatio,
});

公式ドキュメント

ステップ 3 "reglを実行して、描画関数をつくる"

次は、描画関数をつくりましょう。
描画関数を実行することで初めて、つくりたいもの(今回はオレンジ色の三角形)が画面に描画されます。

描画関数は、regl({...})を実行すると返ってくる、
WebGLの構文が詰まった関数になっています。

// バーテックスシェーダー
const vert = `

attribute vec3 a_position;

void main() {
    gl_Position = vec4(a_position, 1.0);
}

`;

// フラグメントシェーダー
const frag = `

precision mediump float;

uniform vec4 u_color;

void main() {
    gl_FragColor = u_color;
}

`;

// attribute修飾子付き変数
const attributes = {
    a_position: [
        [0, 0.5, 0],
        [0.25, -0.25, 0],
        [-0.25, -0.25, 0],
    ],
};

// uniform修飾子付き変数
const uniforms = {
    u_color: [1.0, 0.5, 0.0, 1.0],
};

// 描画関数をつくる。
const draw = regl({
    vert,
    frag,
    attributes,
    uniforms,
    count: attributes.a_position.length,
});

reglの引数にある、

プロパティ名 概要
vert バーテックスシェーダー
frag フラグメントシェーダー
attributes attribute修飾子付き変数
uniforms uniform修飾子付き変数

については、GLSLを書いたことがある方であれば
説明不要だと思いますので、説明を省略します。
countは、「有効な頂点の数」という認識で大丈夫です。
今回は、
attributes.a_position.length(頂点データの数)を
そのままcountに入れていますので、すべての頂点が描画されます。

公式ドキュメント

ステップ 4 "描画関数を実行して、画面に描画する"

さて、それでは描画しましょう!

draw();

これで完了です。
画面を見てみると…なんとも美しい三角形が描画されていることと思います。

ここまでが、reglの基本的な流れです。

  1. canvasの入れ物を用意する
  2. createREGLを実行して、reglインスタンスをつくる
  3. reglを実行して、描画関数をつくる
  4. 描画関数を実行して、画面に描画する

とてもお手軽な感じがしませんか?
(僕はこの、お手軽な感じに惹かれて、GLSLの勉強方法にreglを選びました)
ここまでくれば、あとは公式のexamplesを見れば「なるほどなるほど」と進んでいけると思います。

おわりに

reglは、(特に日本語の)情報が少ないです。
すごくいいこそうと、僕は思っているのですが、使いこなせていないのが現状です。
そのため、上記でお話しした通りのプランでパワーアップしようと企んでいます(他力本願)。

そしてカヤックでは、一緒に企んでくれる仲間を募集中です。
reglが嫌いでも大丈夫です。社内でもreglから目を背けた人がいます。


ほかのWebGL系の記事はこちら。

techblog.kayac.com techblog.kayac.com techblog.kayac.com