ギンの備忘録

デジタルアートやプログラミングやテクノロジー関連のこと。

【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へ配列を渡す方法になります。 調べても中々情報がなかったりするので、この記事が役に立てば幸いです。


関連記事

gin-graphic.hatenablog.com