jsでの音データの使い方メモ
音データを使って、ビジュアル表現をしたかったので音データのとり方を調べました。
続きを読むTouchDesignerのFeedback TOPを使う
Feedback TOPの使い方がイマイチわからなかったのでメモがわりにまとめます。
Feedback TOPは、フレームの映像を薄く残していくために使います。
基本的な使い方は以下のようにオペレーターをループさせて合成していきます。
Feedback TOPは現在のフレームよりも前のフレームを表示してくれる為、ループすることで下のように残像を残すことができます。
続きを読むアルファブレンディングやってみる
アルファブレンディングとはその名の通り、不透明表示のことです。 ポイントはmaterialのtransparent
をtrue
にすることです。
GLSLでテクスチャを貼っているので、フラグメントシェーダー側で透明度を設定します。 ※GLSLでテクスチャを貼っている意味はあまりないです。
続きを読むglslでテクスチャをはる
glsl側でテクスチャを貼ってみたいと思います。 画像はTHREE.ImageUtils.loadTexture
で読み込んでuniform変数として渡します。
渡した画像は、glslのビルドイン関数であるtexture2D
を利用します。 テクスチャの型はsampler2Dを利用します。
precision mediump float; uniform sampler2D uTex; varying vec2 vUv; void main(){ gl_FragColor = texture2D(uTex,vUv); }続きを読む
法線でライトを表現する
WebGLでライトを実装する為に最低限理解しておく必要基礎知識でライトと法線の関係について記載しましたが、実際に法線をつかってライトを表現してみようと思います。
ライトベクトル
ライトの向きのことをライトベクトルと言います。
ライトと記載していますが、ライトの実態は「平行光源」です。 平行光源は3D空間の全てに一様の向きで当たりますので、ライトの向きだけを利用します。
その為、ライトベクトルの値は法線と違い空間上で1つです。どの頂点からみてもライトベクトルの値は同じになります。
ライトベクトルの正規化
ライトベクトルは向きしか利用しない為、正規化して利用します。 正規化にはGLSLのビルドイン関数であるnormalize
を利用します。
vec3 lightDirection = normalize(vec3(0.0, 0.0, 1.0));
ライトの影響度を計算
WebGLでライトを実装する為に最低限理解しておく必要基礎知識でも書きましたが、ライトの影響度はライトベクトルと、法線の内積で求められます。
GLSLでは内積ようの関数であるdot
が用意されています。
使い方はdot(A,B)
のように内積を求める値を引数として設定します。
//ライトの向き vec3 lightDirection = normalize(vec3(0.0, 0.0, 1.0)); //normalは法線の値 float diffuse = max(dot(normal,lightDirection),0.0);
実行結果
実際に、ライトベクトルと法線を使って、ライトを実装してみます。
JS
const myVert = require('./../shader/sample.vert'); const myFrag = require('./../shader/sample.frag'); window.onload = () => { let windowWidth = window.innerWidth; let windowHeight = window.innerHeight; // rendererの作成 let renderer = new THREE.WebGLRenderer(); // canvasをbodyに追加 document.body.appendChild(renderer.domElement); // canvasをリサイズ renderer.setSize(windowWidth, windowHeight); // scene作成 let scene = new THREE.Scene(); // camera作成 let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000); camera.position.z = 1; // Geometry作成 let geometry =new THREE.SphereBufferGeometry( 0.1, 10, 10 ); // Material作成 let material = new THREE.RawShaderMaterial({ vertexShader: myVert, fragmentShader: myFrag, }); // Mesh作成 let mesh = new THREE.Mesh(geometry, material); // Meshをシーンに追加 scene.add(mesh); // draw render(); var r = 0; //描画 function render() { renderer.render(scene, camera); r += 0.01; mesh.rotation.set(0,r,r); // animation requestAnimationFrame(render); } };
vert(頂点シェーダー)
attribute vec3 normal; attribute vec3 position; uniform mat4 modelViewMatrix; uniform mat4 projectionMatrix; uniform mat3 normalMatrix; varying vec4 vColor; const vec3 lightDirection = normalize(vec3(0.0, 0.0, 1.0)); void main() { float diffuse = max(dot(normal,lightDirection),0.0); vColor = vec4(vec3(0.5),1.0) * vec4(vec3(diffuse), 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }
frag(フラグメントシェーダー)
precision mediump float; varying vec4 vColor; void main(){ gl_FragColor = vColor; }
See the Pen RLVZMQ by nogson (@satofaction) on CodePen.
法線の回転
上記の例の場合、ライトの実装はできていますが、オブジェクトを回転させると影もついていってしまいます。 ライトの位置が変わらない場合は、オブジェクトが回転しても影のつき方は、一定方向になるはずです。
なぜ、影も回転してしまうかというと、オブジェクトの回転に合わせて法線の向きも移動させる必要があるからです。 法線の回転を行う為にThree.jsではnormalMatrix
という行列が用意されています。
vec3 n = normalMatrix * normal; float diffuse = max(dot(n,lightDirection),0.0);
normalMatrix(法線を正しい向きにする変換行列)は何をやっているかと言うと、モデル座標変換行列の逆転置行列
を使うようです。
法線を回転した実行結果
See the Pen wrdrvb by nogson (@satofaction) on CodePen.
法線をオブジェクトの回転にあわせて回転させることで、影の方向が一定になりました。
まとめ
とにかくシェーダーは難しいです。慣れるしかなさそうです。。。
TouchDesugberで階層の違うオペレータをつなぐ
Geometry COMP内のTransform SOPなどに違う階層から、値を送るのはどうしたらいいのかなと思っていたら、こちらの記事に書いてありました。
画面左上の「Pane Layout」で画面を分割することができます。 画面を分割することで、階層ごとにオペレータをつなぐことができました。
こんな感じになります。 知らないことが多いですが便利な使い方が沢山ありそうです。
THREE.jsでフラグメントシェーダを使ってみるの基礎基礎メモ1
フラグメントシェーダを使って色を変更してみたいと思います。
基礎の復習
ベースとなるコードです。
js
window.onload = () => { let windowWidth = window.innerWidth; let windowHeight = window.innerHeight; // rendererの作成 let renderer = new THREE.WebGLRenderer(); // canvasをbodyに追加 document.body.appendChild(renderer.domElement); // canvasをリサイズ renderer.setSize(windowWidth, windowHeight); // scene作成 let scene = new THREE.Scene(); // camera作成 let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000); camera.position.z = 100; // Geometry作成 let geometry = new THREE.PlaneBufferGeometry(100, 100); // Material作成 let material = new THREE.ShaderMaterial({ vertexShader: myVert, fragmentShader: myFrag, uniforms:{ uColor: {type: "c", value: new THREE.Color(0xFF0000)} } }); // Mesh作成 let mesh = new THREE.Mesh(geometry,material); // Meshをシーンに追加 scene.add(mesh); // draw renderer.render(scene, camera); };
vert(頂点シェーダー)
void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }
frag(フラグメントシェーダー)
precision mediump float; uniform vec3 uColor; void main(){ gl_FragColor =vec4(uColor, 1.0); }
結果
マウス座標で色を変えてみる
マウス座標を取得して色を変更してみたいと思います。 requestAnimationFrameでuniformsを更新していきます。
js
window.onload = () => { let windowWidth = window.innerWidth; let windowHeight = window.innerHeight; let mouse = new THREE.Vector2(0.0, 0.0); // rendererの作成 let renderer = new THREE.WebGLRenderer(); // canvasをbodyに追加 document.body.appendChild(renderer.domElement); // canvasをリサイズ renderer.setSize(windowWidth, windowHeight); // scene作成 let scene = new THREE.Scene(); // camera作成 let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000); camera.position.z = 100; // Geometry作成 let geometry = new THREE.PlaneBufferGeometry(100, 100); // Material作成 let material = new THREE.ShaderMaterial({ vertexShader: myVert, fragmentShader: myFrag, uniforms: { uMouse: { type: "v2", value: mouse }, } }); // Mesh作成 let mesh = new THREE.Mesh(geometry, material); // Meshをシーンに追加 scene.add(mesh); //マウス座標を取得 renderer.domElement.addEventListener('mousemove', function (e) { mouse = new THREE.Vector2( e.clientX / windowWidth, e.clientY / windowHeight); }, false); // draw render(); //描画 function render() { renderer.render(scene, camera); material.uniforms.uMouse.value = mouse; // animation requestAnimationFrame(render); } };
frag(フラグメントシェーダー)
precision mediump float; uniform vec2 uMouse; void main(){ // テクスチャ座標をカラーに出力 gl_FragColor =vec4(uMouse.x,uMouse.y,0.0, 1.0); }
結果
マウスを動かすと色が変わります。
See the Pen vJqRqb by nogson (@satofaction) on CodePen.
経過時間で色を変えてみる
window.onload = () => { let windowWidth = window.innerWidth; let windowHeight = window.innerHeight; let clock = new THREE.Clock(); let time = 0.0; // rendererの作成 let renderer = new THREE.WebGLRenderer(); // canvasをbodyに追加 document.body.appendChild(renderer.domElement); // canvasをリサイズ renderer.setSize(windowWidth, windowHeight); // scene作成 let scene = new THREE.Scene(); // camera作成 let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000); camera.position.z = 100; // Geometry作成 let geometry = new THREE.PlaneBufferGeometry(100, 100); // Material作成 let material = new THREE.ShaderMaterial({ vertexShader: myVert, fragmentShader: myFrag, uniforms: { uTime: { type: "f", value: time }, } }); // Mesh作成 let mesh = new THREE.Mesh(geometry, material); // Meshをシーンに追加 scene.add(mesh); //マウス座標を取得 renderer.domElement.addEventListener('mousemove', function (e) { mouse = new THREE.Vector2( e.clientX / windowWidth, e.clientY / windowHeight); }, false); // draw render(); //描画 function render() { renderer.render(scene, camera); //経過時間を取得 time = clock.getElapsedTime(); material.uniforms.uTime.value = time; // animation requestAnimationFrame(render); } };
frag(フラグメントシェーダー)
precision mediump float; uniform float uTime; void main(){ float t = abs(cos(uTime)); gl_FragColor =vec4(t,t,t, 1.0); }
結果
See the Pen YxovGW by nogson (@satofaction) on CodePen.
まとめ
すごい基礎的な部分なのですが、なかなか上手くいきません。 とにかく色々やってみるしかありません。