【p5.js】p5.jsからshader(GLSL)へ配列を渡す方法
p5.jsのWEBGLモードではGLSLを利用したshader記述することができます。 p5.jsでsetUniform()を用いることで、GLSLへp5.jsで宣言した値、変数を渡すことができます。
数値を渡す
ここではbool, int, float, vec2, vec3, vec4変数に限定して説明していきます。 その他の変数については理解次第追記していきます。
下のようなuniform変数をフラグメントシェーダで宣言したとします。
フラグメントシェーダ
uniform bool u_flag;
uniform float u_time;
uniform vec2 u_position;
uniform vec4 u_color;
これらにp5.jsから値をセットするには下のように記述します。
p5.js
let flag = true; let position = [0, 0]; theShader.setUniform("u_flag", flag); theShader.setUniform("u_time", 0); theShader.setUniform("u_position", position); theShader.setUniform("u_color", [0.0, 0.0, 1.0, 1.0]);
setUniform()の第1引数はセット対象のuniform変数を指定します。 setUniform()の第2引数は値または変数でセットする値を指定します。
GLSLのvec2, vec3, vec4 変数へsetUniform()する場合は、p5.jsでは配列を指定します。
配列を渡す
続いてbool, int, float, vec2, vec3, vec4変数の配列を uniform変数として宣言する場合を説明します。
以下のように宣言したとします。
フラグメントシェーダ
uniform bool u_flag[2]; uniform float u_time[3]; uniform vec2 u_position[3]; uniform vec4 u_color[2];
GLSLで配列のuniform変数へのsetUniform()は下のように行います。
p5.js
let flag = [true, false, true]; let position = [0, 0, 0.5, 0.1, 1.25, 0.8125]; theShader.setUniform("u_flag", flag); theShader.setUniform("u_time", [0, 1]); theShader.setUniform("u_position", position); theShader.setUniform("u_color", [0.0, 0.0, 1.0, 1.0, 1.0, 0.5, 0.5, 0.5]);
bool, int, float変数の配列であれば、あまり意識せずp5.jsでも同じ要素数の配列を指定すれば問題有りません。
vec2, vec3, vec4変数の場合に注意が必要です。 p5.jsで一次元配列としてセットする値を指定する必要があります。 ベクタの配列なので多次元配列として扱うような思えますが、setUniform()する際にはp5.jsは一次元配列です。 (p5.jsとGLSLの配列の読み出し方の違いなのか詳細までは分かりませんが。。。)
vec2変数の要素3つの配列であれば、p5.jsで下のような配列を渡す必要があります。
[a0, a1, b0, b1, c0, c1]
p5.jsで計算する際は多次元配列で扱って、setUniform()するタイミングで一次元配列を用意するのが理解しやすいコードになると思います。
例えばですが下の様に、計算するときは変数vectorの様に扱い、setUniform()する時は変数u_vectorで一次元配列にして渡すのをおすすめします。
let vector = [[a0, a1], [b0, b1], [c0, c1]]; let u_vector = []; for(let i=0; i<vector.length();i++){ u_vector.push(...vector[i]); }
以上が、p5.jsからshaderへ配列を渡す方法になります。 調べても中々情報がなかったりするので、この記事が役に立てば幸いです。
関連記事