88
coma Creator's session vol.2 田所 淳 1/13, 2014.

coma Creators session vol.2

Embed Size (px)

Citation preview

Page 1: coma Creators session vol.2

coma Creator's session vol.2

田所 淳 1/13, 2014.

Page 2: coma Creators session vol.2

自己紹介

Page 3: coma Creators session vol.2

自己紹介‣ 田所淳 (たどころ あつし) ‣ クリエイティブ・コーダー? ‣ 大学非常勤講師 (多摩美術大学、東京藝術大学) など

Page 4: coma Creators session vol.2

自己紹介‣ http://yoppa.org/

screenshot_679

Page 6: coma Creators session vol.2

今日の内容

Page 7: coma Creators session vol.2

今日の内容‣ ライブ種明かし編!! ‣ coma discotheque ver 0.03 でのライブ ‣ http://www.youtube.com/watch?v=gbVPbc9faXw

Page 8: coma Creators session vol.2

ライブのおおまかなシステム構成‣ だいたいこんな感じ

openFrameworks

GLSL

SuperCollider

映像 音

Page 9: coma Creators session vol.2

ライブのおおまかなシステム構成‣ だいたいこんな感じ !

‣ openFrameworks : ‣ 全体の構造、操作(Key, Mouse) !

‣ GLSL : ‣ グラフィック、アニメーション !

‣ SuperCollider : ‣ 音

Page 10: coma Creators session vol.2

ライブのおおまかなシステム構成‣ openFrameworks + GLSL + SuperCollider ‣ それぞれの内容を、紹介していきます!!

Page 11: coma Creators session vol.2

openFrameworks

Page 12: coma Creators session vol.2

openFrameworks‣ openFrameworks (2005 - ) ‣ Processingの思想を受けつぎつつ、さらに高速化、拡張性を追求した環境

‣ C++による実装 ‣ http://www.openframeworks.cc/

Page 13: coma Creators session vol.2

openFrameworks‣ openFrameworksを何に使用していたか? !

‣ マウスやキーボードの入力 ‣ 全体の構造 (シーンの切り替え)

Page 14: coma Creators session vol.2

openFrameworks‣ openFrameworksを何に使用していたか? !

‣ マウスやキーボードの入力 ‣ 全体の構造 (シーンの切り替え) ← こちらの説明

Page 15: coma Creators session vol.2

openFrameworks + ofxStateMachine

Page 16: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 今回のプロジェクトの構造 ‣ 複数のシーン(状態)の間を自由に移動したい!

Scene A

Scene B

Scene C

Scene D

Page 17: coma Creators session vol.2

void testApp::update(){ switch (state) { case 1: // ... 状態1の処理 ... // break; case 2: // ... 状態2の処理 ... // break; case 3: // ... 状態3の処理 ... // break; // ... } }

openFrameworks + ofxStateMachine‣ mainApp内で、条件によって場合分け? … 面倒くさい

Page 18: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 便利なアドオン紹介 ‣ ofxStateMachine ‣ https://github.com/neilmendoza/ofxStateMachine

Page 19: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ ofxStateMachine ‣ 有限状態機械 (finite state machine)を使用したデザインパターンを実装

Finite State Machine 有限状態機械…??

Page 20: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 有限状態機械 → oFで解釈すると… ‣ 複数の状態(State)をテンプレートから生成

State Template

StateA

StateB

StateC

Page 21: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 有限状態機械 → oFで解釈すると… ‣ それぞれの状態(State)を相互に行き来可能

StateA

StateB

StateC

Page 22: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 使い方は簡単! ‣ ofxState : それぞれの状態のテンプレートとなるクラス、継承して使用する

‣ SharedData : 全てのクラスで共有するデータ

ofxState State A

State B

State C

継承

SharedData

参照

Page 23: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ ofxStateには、ofBaseApp (つまりtestAppクラス) で定義されているメソッドが組込まれている

‣ setup(), update(), draw(), mouseReleased(), keyPressed() … !

‣ つまり、一つのプロジェクトの中に、沢山のoFアプリが入っているような感覚でコーディング可能!!

project

ofBaseAppofBaseAppofBaseApp

Page 24: coma Creators session vol.2

class MyState : public itg::ofxState<> { public: void setup(); void update(); void draw(); ! ... ! string getName(); };

openFrameworks + ofxStateMachine‣ Stateのテンプレート

Page 25: coma Creators session vol.2

class MyState : public itg::ofxState<> { public: void setup(); void update(); void draw(); ! ... ! string getName(); };

openFrameworks + ofxStateMachine‣ Stateのテンプレート

← ココ重要!

Page 26: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 各Stateは、名前を呼ぶと表示される ‣ 《Stateのインスタンス》.getName() で名前を返すようにする ‣ testAppから名前を呼ぶと、Stateが選択される

testApp State A

State B

State C

“state_a”

“state_b”

“state_c”

Page 27: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 各Stateは、名前を呼ぶと表示される ‣ 《Stateのインスタンス》.getName() で名前を返すようにする ‣ testAppから名前を呼ぶと、Stateが選択される

testApp State A

State B

State C

“state_a”

“state_b”

“state_c”

changeState(“state_b”)

Page 28: coma Creators session vol.2

openFrameworks + ofxStateMachine‣ 各Stateは、名前を呼ぶと表示される ‣ 《Stateのインスタンス》.getName() で名前を返すようにする ‣ testAppから名前を呼ぶと、Stateが選択される

testApp State A

State B

State C

“state_a”

“state_b”

“state_c”

changeState(“state_b”)

表示

Page 29: coma Creators session vol.2

ofxStateMachine Demo: コード実例でみてみる!

Page 30: coma Creators session vol.2

GLSL (Shader)

Page 31: coma Creators session vol.2

GLSL (Shader)‣ 今回の画面の表示は、全てGLSL (OpenGL Shading Language) をつかった

‣ とっつきずらいが、綺麗、速い!

Page 32: coma Creators session vol.2

GLSL (Shader)‣ GLSLを試行錯誤したい!! ‣ addonを作成しました → ofxGLSLSandbox ‣ https://github.com/tado/ofxGLSLSandbox

Page 33: coma Creators session vol.2

GLSL (Shader)‣ ofxGLSLSandbox ‣ ウリは、Live Edit機能!! ‣ プログラムを動作させながら、Shaderを書き換えできる ‣ やりかたは後で

Page 34: coma Creators session vol.2

GLSL (Shader)‣ ofxGLSLSandbox ‣ ウリは、Live Edit機能!! ‣ プログラムを動作させながら、Shaderを書き換えできる ‣ やりかたは後で

Page 35: coma Creators session vol.2

GLSL (Shader)‣ ofxGLSLSandboxで、Shaderを書きながら基本を学ぼう!

Page 36: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red. }

GLSL (Shader)‣ まずは、基本形

Page 37: coma Creators session vol.2

GLSL (Shader)‣ 真っ赤な画面になるはず ‣ gl_FlagColor → 全てのピクセルの色を指定している ‣ vec4(…); → 色を指定(RGBA)

Page 38: coma Creators session vol.2

GLSL (Shader)‣ 上にある3つの「uniform」は何か? ‣ openFrameworksから渡されている値 !

‣ uniform float time; → 経過時間(Second) ‣ uniform vec2 mouse; → マウスの位置 (x, y) ‣ uniform vec2 resolution; → 画面の大きさ (x, y) !

‣ 手始めに、resolutionをつかってみる

Page 39: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ float br = gl_FragCoord.x / resolution.x; gl_FragColor = vec4(br, br, br, 1.0); }

GLSL (Shader)‣ 座標の値を利用してグラデーションをつくる

Page 40: coma Creators session vol.2

GLSL (Shader)‣ x軸方向へのグラデーションになる

Page 41: coma Creators session vol.2

GLSL (Shader)‣ gl_FragCoord → ウィンドウ上でのフラグメントの位置(x, y) ‣ gl_FragCoord.x : x方向 ‣ gl_FragCoord.y : y方向 ‣ gl_FragCoord.xy : 2次元平面 (vec2)

Page 42: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec3 color; color.r = gl_FragCoord.x / resolution.x; color.g = 0.2; color.b = gl_FragCoord.y / resolution.y; gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ RGBごとに別の値に

Page 43: coma Creators session vol.2

GLSL (Shader)‣ カラフルなグラデーション完成!!

Page 44: coma Creators session vol.2

GLSL (Shader)‣ 次に時間を操作してみる ‣ timeを使用 !

‣ 時間によって色の濃度を変化させるとどうなるか? ‣ 定期的な色の変化を、時間とsin関数で生成してみる

Page 45: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec3 color; color.r = sin(time * 1.0); color.g = sin(time * 1.7); color.b = sin(time * 2.3); gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ 時間変化

Page 46: coma Creators session vol.2

GLSL (Shader)‣ 時間によって、色が変化していくはず!

Page 47: coma Creators session vol.2

GLSL (Shader)‣ sin関数に、gl_FragCoord(座標) を入れるとどうなるか? ‣ 実験!!

Page 48: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec3 color; color.r = sin(gl_FragCoord.x / 10.0); color.g = sin(gl_FragCoord.x / 13.0); color.b = sin(gl_FragCoord.x / 17.0); gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ gl_FragCoordとSin関数

Page 49: coma Creators session vol.2

GLSL (Shader)‣ 縞々模様に!

Page 50: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec3 color; color.r = sin(gl_FragCoord.x / 10.0 + time * 5.0); color.g = sin(gl_FragCoord.x / 13.0 + time * 6.0); color.b = sin(gl_FragCoord.x / 17.0 + time * 7.0); gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ さらに時間(time)を足してみる

Page 51: coma Creators session vol.2

GLSL (Shader)‣ 縞模様が左右に動く(はず)

Page 52: coma Creators session vol.2

GLSL (Shader)‣ 濃度ではなく、(x, y)座標にsinwaveを描いてみる ‣ ちょっと複雑… !

‣ 少しずつやってみる

Page 53: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec2 pos = ( gl_FragCoord.xy / resolution.xy ); vec3 color = vec3(pos.y); gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ はじめの一歩: y座標の位置で色を変化 = グラデーション

Page 54: coma Creators session vol.2

GLSL (Shader)‣ グラデーション

Page 55: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec2 pos = ( gl_FragCoord.xy / resolution.xy ); pos.y -= 0.5; pos.y += sin(pos.x * 10.0 + time) * 0.2; vec3 color = vec3(pos.y); gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ グラデーションのy座標を、sin関数で変化させてみる

Page 56: coma Creators session vol.2

GLSL (Shader)‣ 波うつグラデーションができた

Page 57: coma Creators session vol.2

GLSL (Shader)‣ 明度の絶対値を表示してみる

明度

y座-1

1

明度

y座-1

1

Page 58: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec2 pos = ( gl_FragCoord.xy / resolution.xy ); pos.y -= 0.5; pos.y += sin(pos.x * 10.0 + time) * 0.2; ! vec3 color = vec3(abs(pos.y)); ! gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ 明度の絶対値を表示してみる

Page 59: coma Creators session vol.2

‣ 波の形が見えてきた!!

GLSL (Shader)

Page 60: coma Creators session vol.2

GLSL (Shader)‣ さらに1から引いて、乗算する

明度

y座-1

1

明度

y座-1

1

Page 61: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec2 pos = ( gl_FragCoord.xy / resolution.xy ); pos.y -= 0.5; pos.y += sin(pos.x * 10.0 + time) * 0.2; ! vec3 color = vec3(1.0 - pow(abs(pos.y),0.2)); ! gl_FragColor = vec4(color, 1.0); }

GLSL (Shader)‣ さらに1から引いて、乗算する

Page 62: coma Creators session vol.2

‣ きれいなSin波が描けた!!

GLSL (Shader)

Page 63: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec2 pos = ( gl_FragCoord.xy / resolution.xy ); pos.y -= 0.5; pos.y += sin(pos.x * 10.0 + time) * 0.2; vec3 color = vec3(1.0 - pow(abs(pos.y),0.2)); ! gl_FragColor = vec4(color.r*0.2, color.g*0.5, color.b*1.0, 1.0); !}

GLSL (Shader)‣ 色合いを工夫してみる

Page 64: coma Creators session vol.2

‣ 自分の好みの色に!!

GLSL (Shader)

Page 65: coma Creators session vol.2

uniform float time; uniform vec2 mouse; uniform vec2 resolution; !void main(void){ vec2 pos = ( gl_FragCoord.xy / resolution.xy ); pos.y -= 0.5; ! pos.y += sin(pos.x * 10.0 + time) * 0.2 * sin(time); ! vec3 color = vec3(1.0 - pow(abs(pos.y),0.2)); gl_FragColor = vec4(color.r*0.2, color.g*0.5, color.b*1.0, 1.0); }

GLSL (Shader)‣ さらに時間で振幅を変化させてみたり

Page 66: coma Creators session vol.2

‣ 完成!!

GLSL (Shader)

Page 67: coma Creators session vol.2

GLSL (Shader)‣ openFrameworksとGLSLの連携をしてみる ‣ このSin波のパラメータを、oFで生成して渡してみる !

‣ oF側 → float array[] を生成し、setUniform1fv() で渡す ‣ GLSL側 → uniform float array[] で受ける !

‣ oF側でランダムにパラメータ生成して、Shaderに入れてみる!

Page 68: coma Creators session vol.2

#include "testApp.h" !//波の数 static const int NUM = 20; //Shaderへ渡す周波数の配列 float freq[NUM]; !void testApp::setup(){ //Shaderの画面サイズ設定 width = 400; height = 300; fbo.allocate(width, height); //Shaderファイルの読込み shader.load("shader"); //ランダムに周波数の配列を生成 for (int i = 0; i < NUM; i++) { freq[i] = ofRandom(4.0, 10.0); } }

GLSL (Shader)‣ Shader側

Page 69: coma Creators session vol.2

#include "testApp.h" !//波の数 static const int NUM = 20; //Shaderへ渡す周波数の配列 float freq[NUM]; !void testApp::setup(){ //Shaderの画面サイズ設定 width = 400; height = 300; fbo.allocate(width, height); //Shaderファイルの読込み shader.load("shader"); //ランダムに周波数の配列を生成 for (int i = 0; i < NUM; i++) { freq[i] = ofRandom(4.0, 10.0); } }

GLSL (Shader)‣ openFrameworks: testApp.cpp

Page 70: coma Creators session vol.2

void testApp::draw(){ //Shaderパラメータ設定 float resolution[] = {width, height}; float mousePoint[] = {mouse.x, mouse.y}; float time = ofGetElapsedTimef(); //FBO開始 fbo.begin(); shader.begin(); //Shaderに渡す値(時間、解像度、マウスの位置) shader.setUniform1f("time", time); shader.setUniform2fv("resolution", resolution); shader.setUniform2fv("mouse", mousePoint); //freqの配列をShaderに渡す shader.setUniform1fv("freq", freq, NUM); ! //画面全体に描画する ofRect(0, 0, ofGetWidth(), ofGetHeight()); shader.end(); fbo.end(); fbo.draw(0, ofGetHeight(), ofGetWidth(), -ofGetHeight()); }

GLSL (Shader)‣ openFrameworks: testApp.cpp

Page 71: coma Creators session vol.2

‣ 折り重なる様々な周波数のSin波

GLSL (Shader)

Page 72: coma Creators session vol.2

SuperCollider

Page 73: coma Creators session vol.2

SuperCollider Basics

‣ Sup

Page 74: coma Creators session vol.2

SuperCollider Basics‣ SuperColliderとは? ‣ リアルタイムな音響合成やアルゴリズミック・コンポジションのためのプログラミング言語

‣ SmallTalkライクなオブジェクト指向言語 ‣ リアルタイムに音響を生成できる → ライブコーディング!

Page 75: coma Creators session vol.2

SuperCollider Basics‣ 1996年にJames McCartneyによりリリース ‣ James McCartneyの就職(Apple!)などの事情で、オープソースとして公開

‣ 現在は、GPLライセンスとして多くの開発者により更新されている

Page 76: coma Creators session vol.2

SuperCollider Basics‣ 参考図書:The SuperCollider Book ‣ Wilson, S., Cottle, D. and Collins, N. (eds). 2011. The SuperCollider Book. Cambridge, MA: MIT Press

Page 77: coma Creators session vol.2

SuperCollider Basics‣ Website: http://supercollider.sourceforge.net/

Page 78: coma Creators session vol.2

SuperCollider Basics‣ SuperColliderをダウンロード ‣ 最新版は、version 3.6.5 (2013年10月現在) ‣ http://supercollider.sourceforge.net/downloads/

Page 79: coma Creators session vol.2

The SuperCollider Language‣ SuperColliderの独特な文法 ‣ Smalltalkのオブジェクト指向な言語構造と、C言語系の制御構造などの機能を足したような感じ

// print "Hello world!"!"Hello world!".postln;!// play a mixture of an 800 Hz sine tone and pink noise!{ SinOsc.ar(800, 0, 0.1) + PinkNoise.ar(0.01) }.play;!// modulate a sine frequency and a noise amplitude with another sine!// whose frequency depends on the horizontal mouse pointer position!{ ! var x = SinOsc.ar(MouseX.kr(1, 100));! SinOsc.ar(300 * x + 800, 0, 0.1) ! + ! PinkNoise.ar(0.1 * x + 0.1) !}.play;!// list iteration: multiply the elements of a collection by their indices![1, 2, 5, 10, -3].collect { ! arg elem, idx;! elem * idx;!};!// factorial function!f = {! arg x;! if(x == 0) { 1 } { f.(x-1) * x }!};

Page 80: coma Creators session vol.2

//楽器基本 SynthDef("col_closesaw", { arg fadeTime = 10, n = 0, rq = 0.3, detune = 0.001, base = 20, ratio = 1.5, harm = 1.5, amp = 0.2, gate=0; var lfo, env, out; env = EnvGen.kr(Env.new([0,1], [fadeTime], 'sine')); lfo = SinOsc.ar(rrand(0.03, 0.05), 0, 100, 600); out = Saw.ar([base+detune.rand, base+detune.rand] * (ratio ** n)) * amp + Saw.ar([base*harm+detune.rand, base*harm+detune.rand] * (ratio ** n)) * amp; out = out * env; out = RLPF.ar(out, lfo * (1.5 ** n), rq).clip2 * 0.5; out = out * EnvGen.kr(Env.adsr(releaseTime:20), gate, doneAction: 2); Out.ar(0, out); }).store;

The SuperCollider Language‣ 冒頭のドローン系の音を解説 ‣ 楽器はこんな感じ - 1.5倍の比率でノコギリ波を重ねている

Page 81: coma Creators session vol.2

Synth("col_closesaw",["n", 1, "gate", 1]);

The SuperCollider Language‣ 演奏してみる ‣ …ちょっと味気ない

Page 82: coma Creators session vol.2

!SynthDef("col_closefx", { arg lpf=440, rq=0.5, amp=0.8; var in, out; in = In.ar(0, 2); 12.do({ in = AllpassL.ar(in, 0.1, LFNoise2.kr([rrand(0.0, 0.1),rrand(0.0, 0.1)],0.01,0.06), 4.0) }); out = CompanderD.ar(in) * amp; ReplaceOut.ar(0, out); }).store;

The SuperCollider Language‣ エフェクトを加えてみる ‣ オールパス・フィルタを幾重にも重ねていく

Page 83: coma Creators session vol.2

Synth("col_closefx"); Synth("col_closesaw",["n", 0, "gate", 1]);

The SuperCollider Language‣ エフェクト付きで演奏してみる ‣ ぐっと深みが増した

Page 84: coma Creators session vol.2

Synth("col_closesaw",["n", 1, "gate", 1]); Synth("col_closesaw",["n", 2, "gate", 1]); Synth("col_closesaw",["n", 3, "gate", 1]); Synth("col_closesaw",["n", 4, "gate", 1]); Synth("col_closesaw",["n", 5, "gate", 1]); Synth("col_closesaw",["n", 6, "gate", 1]); Synth("col_closesaw",["n", 7, "gate", 1]); Synth("col_closesaw",["n", 8, "gate", 1]); Synth("col_closesaw",["n", 9, "gate", 1]); Synth("col_closesaw",["n", 10, "gate", 1]); Synth("col_closesaw",["n", 11, "gate", 1]); ...

The SuperCollider Language‣ どんどん倍音を足していく ‣ ある値を境に、突然非線形に歪んでドラマチックな展開へ

Page 85: coma Creators session vol.2

まとめ

Page 86: coma Creators session vol.2

まとめ‣ 駆け足で、それぞれの要素を解説してきた

openFrameworks

GLSL

SuperCollider

映像 音

Page 87: coma Creators session vol.2

まとめ‣ openFrameworks ‣ SuperCollider ‣ GLSL !

‣ どれもフリーウェア ‣ ネットで調べると、情報もたくさん !

‣ 適材適所で開発環境を使い分け

GLSL

SuperCollider

Page 88: coma Creators session vol.2

まとめ‣ 今後も様々な情報を交換していきましょう!!

GLSL

SuperCollider