【p5.js】自作Shapeにシェーダーを適用する
p5.jsで自作したShapeにシェーダーを適用していきます。
自作Shapeは前回の記事で扱った正多角形を使います。
自作図形にシェーダー適用
自作図形にシェーダー適用する際に必要なことが2つあります。
textureModeの設定
vertex関数でテクスチャ座標(uv座標)を設定
この2つの設定を行うことで、自作した図形にシェーダーが適用されます。
textureModeの設定
setupとしてtextureMode(NORMAL);
を宣言する必要があります。
これにより自作図形にシェーダーを適用するテクスチャモードを選択します。
createCanvas(500, 500, WEBGL); colorMode(HSB); textureMode(NORMAL); theShader = createShader(vs, fs); noStroke();
上のような形でsetupしておきます。 Shaderは適用したいものを用意して下さい。
テクスチャ座標の設定
図形を作成する際はvertex()関数でテクスチャ座標(uv座標)を指定する必要があります。 テクスチャ座標はテクスチャの貼り付ける位置情報の様なものです。
vertex(x, y, z, u, v)
と引数を渡すことで定義されます。
このu, vは0から1の間で指定する必要があります。 図形の大きさを1として引数を計算することになります。
正多角形を描画するコードにテクスチャ座標の設定を追加しました。
function Polygon(x, y, size, pointNum){ const outsideRadius = size; const angleStep = 2*PI/pointNum ; let angle = 0; beginShape(); for(let i=0;i<=pointNum;i=i+1){ let px = x + outsideRadius*cos(angle); let py = y + outsideRadius*sin(angle); vertex(px, py, 0, 0.5+cos(angle)/2, 0.5+sin(angle)/2); angle = angle + angleStep; } endShape(CLOSE); }
vertex(px, py, 0, 0.5+cos(angle)/2, 0.5+sin(angle)/2);
として、頂点の座標を0から1に正規化した値をセットします。
実際にシェーダーを適用した正多角形が下になります。 例として正六角形を描画しました。
また、今回は2色のグラデーションを描画する以下のShaderを使っています。
let vs = ` precision highp float; attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform mat4 uProjectionMatrix; uniform mat4 uModelViewMatrix; void main() { vec4 positionVec4 = vec4(aPosition, 1.0); vTexCoord = aTexCoord; gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; } `; let fs = ` precision highp float; varying vec2 vTexCoord; uniform vec3 u_color0; uniform vec3 u_color1; void main() { vec2 b = vTexCoord; vec3 c0 = u_color0 / 255.0; vec3 c1 = u_color1 / 255.0; vec3 col = (c0 * (b.x+b.y)/2.0) + (c1 * (2.0-b.x-b.y)/2.0) ; vec4 gcolor = vec4(col, 1.0); gl_FragColor = gcolor; } `;
正多角形(外周)へシェーダー適用
次に正多角形で、外周のみの描画をした図形にシェーダーを適用します。 真ん中が空いた様な図形ですが、設定することは変わりません。
頂点座標をセットする際に、テクスチャ座標を指定していきます。
function outlinePoly(x, y, size, weight, pointNum){ const outsideRadius = size; const insideRadius = size - weight ; const angleStep = 2*PI/pointNum ; let angle = 0; beginShape(TRIANGLE_STRIP); for(let i=0;i<=pointNum;i=i+1){ let px = x + outsideRadius*cos(angle); let py = y + outsideRadius*sin(angle); vertex(px, py, 0, 0.5+cos(angle)/2, 0.5+sin(angle)/2); px = x + insideRadius*cos(angle); py = y + insideRadius*sin(angle); vertex(px, py, 0, 0.5+cos(angle)/2, 0.5+sin(angle)/2); angle = angle + angleStep; } endShape(CLOSE); }
正六角形で中が空いた図形にシェーダー適用ができました。
作例
三角形から十角形までを並べて描いた作例が下になります。 どの図形にもシェーダーでグラデーションを適用できています。