3Dモデル
3DCGツールで作成した3Dモデル(立体のキャラクターなどのデータ)を読み込んで表示できます
*p5.jsでは同じドメイン内からしか3Dモデルを読み込めません
loadModel(path, normalize, [successCallback], [failureCallback], [fileType])
OBJファイルまたはSTLファイルから 3Dモデルを読み込みますpreload()内に配置する必要があります
サイズが大きい場合は第二引数にtrueを設定(p5に適したスケールに変更)
scale() 関数で最終的なサイズにできます- path
ロードするモデルのパス - normalize:
true の場合読み込み時にモデルを標準化されたサイズにスケーリングします - successCallback
モデルが読み込まれると呼び出される関数
3Dモデルオブジェクトが渡されます - failureCallback:
モデルの読み込みに失敗した場合、イベントエラーで呼び出されます - fileType
モデルのファイル拡張子 「.stl・.obj」
- path
model()
3Dモデルを画面にレンダリングします
- OBJファイル(.obj)
ジオメトリと一部のマテリアルおよびテクスチャデータを格納するファイル形式
p5.js ではジオメトリのみ - STLファイル(.stl)
ジオメトリに関する情報のみ格納するファイル形式
p5.jsでは色付きのSTLファイルはサポートされていません
*色付きの STLファイルは色のプロパティなしでレンダリングされます
let chair;
function preload() {
chair = loadModel('chair.obj', true);
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
}
function draw() {
background(200);
scale(0.5);
rotateX(frameCount * 0.01);
rotateY(frameCount * 0.01);
normalMaterial();
model(chair);
}
無料で3Dモデルがダウンロードできるサイト
シェーダー(GLSL)入門
シェーダーはGPUで実行される「色の計算に特化した小さなプログラム」です。従来のp5.js(CPU)が一つずつ順番に描画するのに対し、シェーダー(GPU)は数百万ピクセルを同時に計算するため、圧倒的に高速で複雑な表現が可能です。
1. 二つの役割:Vertex & Fragment
GLSLでは、必ず以下の2つのファイルをセットで記述します。これが「形」と「色」の役割分担です。
役割:「どこに」描くかを決める。
3D空間の点を、画面上の2D座標に変換します。頂点ごとに1回実行されます。
役割:「どんな色で」塗るかを決める。
頂点に囲まれた中身(ピクセル)の色を決定します。全ピクセルで同時に実行されます。
2. 【なぜ?】座標を計算し直す理由
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
p5.jsの通常モード(Canvas)は左上が原点ですが、GPUの世界(WEBGL)は「中心が (0,0)、範囲は -1.0 〜 1.0」というルールがあります。この一文は、0〜1の座標系を、GPUが理解できる -1〜1 の世界へ引き伸ばすための「翻訳」作業です。
3. JavaScriptからデータを送る「Uniform」
CPU(JS)で計算した「時間」や「解像度」をGPUへ届けるための専用ポストがUniform(ユニフォーム)です。
theShader.setUniform(“u_resolution”, [width, height]);
uniform vec2 u_resolution;
4. 実装のワークフロー
preload():loadShader()でファイルを読み込む。setup():createCanvas(..., WEBGL)でWEBGLモードを起動。draw():shader(theShader)を適用し、setUniformでデータを送る。
シェーダーは「インク」のようなものです。設定しただけでは何も映りません。draw() の最後で rect(0,0,width,height) などの「キャンバスとなる形状」を描画するのを忘れないようにしましょう!その形に対して、初めてシェーダーが反映されます。
let theShader;
function preload() {
theShader = loadShader('shader.vert', 'shader.frag');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
pixelDensity(1);
noStroke();
}
function draw() {
shader(theShader);
theShader.setUniform("u_resolution", [width, height]);
theShader.setUniform("u_time", millis() / 1000.0);
//シェーダーを任意の形状に適用、形状を指定しない限りシェーダーは機能しない
rect(0,0,width, height);
}
function windowResized(){
resizeCanvas(windowWidth, windowHeight);
}2つのテンプレート(備忘録)
シェーダーには、「最初から0〜1に整っている住所」を使うパターンと、「実際のピクセル数」から計算するパターンの2つがあります。
| 割合(vTexCoord) | 頂点シェーダーから届く「割合」を使う 計算がシンプルで、p5.jsと相性がいい uv = vTexCoord * 2.0 - 1.0 |
| ピクセル(gl_FragCoord) | 画面の「ドットの数」を直接使う 他のサイト(ShaderToyなど)のコードを移植しやすい uv = (gl_FragCoord.xy * 2.0 – uResolution.xy) / min |
vTexCoord を使う「モダン・スタイル」
p5.jsが最初から「ここが端っこだよ」と教えてくれる数値を使う、一番スマートな書き方です。
//shader.vert(頂点シェーダー)
precision highp float;
attribute vec3 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord; // フラグメントシェーダーに送る「連絡通路」
void main() {
vTexCoord = aTexCoord; // 0.0〜1.0の住所をそのまま渡す
vec4 positionVec4 = vec4(aPosition, 1.0);
// キャンバスを画面いっぱいに広げるおまじない
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
gl_Position = positionVec4;
}//shader.frag(フラグメントシェーダー)
precision highp float;
precision highp int;
varying vec2 vTexCoord;
uniform vec2 uResolution;
uniform float uTime;
void main() {
// 1. 0〜1を「-1〜1」の範囲に直す(真ん中を 0,0 にする)
vec2 uv = vTexCoord * 2.0 - 1.0;
// 2. 画面の比率(アスペクト比)を直す
uv.x *= uResolution.x / uResolution.y;
// ここから魔法を書く
float d = length(uv);
gl_FragColor = vec4(vec3(step(0.3, d)), 1.0);
}gl_FragCoord を使う「クラシック・スタイル」
「左から何ピクセル目、下から何ピクセル目」という生のデータを、自分で割って計算するタフな書き方です。
//shader.vert(頂点シェーダー)
attribute vec3 aPosition;
void main() {
vec4 positionVec4 = vec4(aPosition, 1.0);
// 画面の真ん中を (0,0) にする魔法!
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
gl_Position = positionVec4;
}//shader.frag(フラグメントシェーダー)
precision highp float;
uniform vec2 uResolution;
uniform float uTime;
void main() {
// 1. ピクセル座標(0〜1920など)を一気に「-1〜1」の割合に変換!
// min(x, y) で割ることで、短い方の辺を基準にして比率を合わせる
vec2 uv = (gl_FragCoord.xy * 2.0 - uResolution.xy) / min(uResolution.x, uResolution.y);
// ここから魔法を書く
float d = length(uv);
gl_FragColor = vec4(vec3(step(0.3, d)), 1.0);
}見つける😊
*OpenProcessingは、Processingの作品を公開したり共有したりできるサイトです
