第5回 クリエイティブ・コード・スケッチ テーマ 画像と映像
クリエイティブ・コード・スケッチ・クラブという活動を5-6名で社内でやってます。週1回お題に沿ってJavaScriptや3Dソフトなどでデモを作り、作ったものを発表してます。
10月から活動を開始し、11/25で5回目になりました。デモレベルの作品を定期的にアウトプットして、知見を共有するのが目的です。
第1回 - 第4回は今後共有するとして、今回は第5回のデモについてざっくり説明します。
デモ
コード
デモはthree.jsを使用して実装して、WebGL上で実行しています。
取得した映像の色データを白黒データとしてグリッドで取得し、白黒の値からフォントを0-8の9つの値として表示しています。
three.jsを使用した映像の全画面表示
three.jsは名前に3(three)が入ってる通りWebGL上で3Dを簡単に実装するためのライブラリです。
three.jsの「WebGL上で3Dを簡単に実装する」という仕組みを理解すれば、2Dの全画面表示は簡単にできます。(WebGLは3DをレンダリングするためのAPIではないので、2D描画でthree.jsを使用すると少し無駄な行列計算をしています。最適化したいときはWebGL APIを直接書くことをおすすめします。)
遠近法のないカメラであるorthographicカメラを使用します。
カメラのスケールを画面サイズに設定して、表示領域を把握しやすくします。
var width = window.innerWidth;
var height = window.innerHeight;
this.camera = new THREE.OrthographicCamera(
width / -2,
width / 2,
height / 2,
height / -2,
1,
100
);
1x1の平面planeをgeometryにしたmeshを作成し、画面サイズに応じていい感じにフィットすようにリサイズします。
var plane = new THREE.PlaneGeometry(1, 1);
var material = // 略
var mesh = new THREE.Mesh(plane, material);
var width = window.innerWidth; // 横画面サイズ
var height = window.innerHeight; // 縦画面サイズ
let meshWidth, meshHeight; // meshのスケール
// メッシュのスケールを計算する
if ((videoHeight / videoWidth) * width > height) {
meshWidth = width;
meshHeight = (videoHeight / videoWidth) * videoWidth;
} else {
meshHeight = height;
meshWidth = (videoWidth / videoHeight) * videoHeight;
}
mesh.scale.set(meshWidth, meshHeight, 1);
デモで使用しているフラグメントシェーダー
フラグメントシェーダーとして以下のファイルを使用しています。
precision highp float;
uniform sampler2D uTexture;
uniform sampler2D uFontTexture;
uniform vec2 uWindowSize;
uniform float uGridSize;
uniform float uProgress;
uniform float uProcess;
varying vec2 vUv;
void main(){
// プロセス1
vec2 windowSize = vUv * uWindowSize;
vec2 gridIndex = floor(windowSize/uGridSize);
vec2 customUv = (gridIndex * uGridSize)/uWindowSize;
vec4 textureColor = texture2D(uTexture, customUv);
float blackWhite = (textureColor.r + textureColor.g + textureColor.b )/3.;
if(uProcess == 1.0){
// プロセス2
vec2 gridUv = (windowSize - gridIndex * uGridSize) / uGridSize;
gridUv.x = 1.0 - gridUv.x;
float rate = floor(mix(6., blackWhite * 9., uProgress));
float col = mod(rate, 3.);
float row = floor(rate / 3.);
vec2 outputUv = vec2(gridUv.x / 3. + 0.333 * col, gridUv.y/3. + 0.333 * row);
vec4 outColor = texture2D(uFontTexture, outputUv);//vec4(gridUv, 0.0, 1.0);
gl_FragColor = outColor;
}else{
// プロセス2を表示
gl_FragColor = vec4(blackWhite, blackWhite, blackWhite, 1.0);
}
}
プロセスとしては2つだけです。
プロセス1 グリッドサイズをベースに 白黒の値を取得する
プロセス2 グリッドサイズの白黒の値をベースにフォントを適用する
この記事が気に入ったらサポートをしてみませんか?