0
Media Art II 2013
第7回 : openFrameworks
3Dグラフィクス、OpenGL
多摩美術大学情報デザイン学科メディア芸術コース
2013年10月28日
田所 淳
今日の内容
‣

openFrameworksの、3D機能、OpenGLの機能を中心に
取り上げます
今日の内容
‣

3DやOpenGLに関する機能を概観します
クラス名

機能

ofBox, ofSphere

3Dプリミティブオブジェクトの描画

ofEasyCam

簡単に利用可能なカメラ(視点)機能

ofLight

ライティング...
3Dプリミティブ図形の描画
ofBox、ofSphere
3Dプリミティブ図形の描画 ofBox、ofSphere
‣

openFrameworks v080から、3Dの基本図形の描き方が
変化
!

‣

球体: ofSphere → ofSpherePrimtive

‣

立方体: ofBox...
3Dプリミティブ図形の描画 ofBox、ofSphere
‣

testApp.h

#pragma once

!

#include "ofMain.h"

!

class testApp : public ofBaseApp{
publ...
3Dプリミティブ図形の描画 ofBox、ofSphere
‣

testApp.cpp

#include "testApp.h"

!

void testApp::setup(){
ofBackground(0);
}

!

void t...
3Dプリミティブ図形の描画 ofBox、ofSphere
‣

完成!!
視点をインタラクティブに移動
ofEasyCam
視点をインタラクティブに移動 - ofEasyCam
‣

次に、この図形を様々な角度から眺められるようにする

‣

物体を動かすのではなく、視点(カメラ)を移動して、物体
を注視する角度を変更してみる

‣

視点を指定するofEasyCa...
視点をインタラクティブに移動 - ofEasyCam
‣

testApp.h

#pragma once

!

#include "ofMain.h"

!

class testApp : public ofBaseApp{
public...
視点をインタラクティブに移動 - ofEasyCam
‣

testApp.cpp

… (前略) …

!

void testApp::draw(){
cam.begin(); // カメラ開始
ofSetColor(255);
// 立方...
視点をインタラクティブに移動 - ofEasyCam
‣

testApp.cpp

… (前略) …

!

void testApp::draw(){
cam.begin(); // カメラ開始
ofSetColor(255);
// 立方...
視点をインタラクティブに移動 - ofEasyCam
‣

マウスをドラッグすると物体を回転できる
ライティング
ofLight
ライティング - ofLight
‣

プリミティブを描画する命令
‣
‣

‣

プリミティブ.drawWireframe() → ワイヤーフレーム
プリミティブ.draw() → 塗り潰し

実際にやってみる
ライティング - ofLight
‣

testApp.cpp

void testApp::draw(){
cam.begin(); // カメラ開始
ofSetColor(255);
// 立方体
box.set(200); // サイズ設...
ライティング - ofLight
‣

陰影も何もない、のっぺりとした図形になってしまう
ライティング - ofLight
‣

なぜ、陰影のないのっぺりとした図形になってしまうのか?

‣

ライティングがされていないから

‣

適切な照明を物体に照射することで、リアルな陰影が表現
される

‣

ofLightクラスを使用する
ライティング - ofLight
‣

ofLightでは「Phongシェーディング」というアルゴリズ
ムで、物体にリアルな陰影や反射を付加している

‣

3Dグラフィックにおいて、モデリングされた面上の点に
影をつけるための照明と陰影モデル...
ライティング - ofLight
‣

Phongシェーディング

‣

3つの光の反射の強度と色を指定する
‣

鏡面反射 (Specular)

‣

拡散反射 (Diffuse)

‣

環境反射 (Ambient)
ライティング - ofLight
‣

testApp.h

#pragma once

!

#include "ofMain.h"

!

class testApp : public ofBaseApp{
public:
void set...
ライティング - ofLight
‣

testApp.cpp

… (前略) …

!

void testApp::setup(){
ofBackground(0);
// ライティングを有効に
light.enable();
// スポッ...
ライティング - ofLight
‣

立体のの前後の重なりが、おかしい!?
ライティング - ofLight
‣

openFrameworksでは、そのままの設定では後から実行
した命令がどんどん上のレイヤーに描かれる

‣

3Dの立体の場合、有り得ない重なりになることも

‣

DEPTH TEST (深度テスト...
ライティング - ofLight
‣

testApp.cpp を修正

… (前略) …

!

void testApp::setup(){
ofBackground(0);
ofEnableDepthTest(); // 深度テストを有効...
ライティング - ofLight
‣

正しい重なりに
メッシュ (頂点情報の集合)
ofMesh
メッシュ (頂点情報の集合) - ofMesh
‣

立方体や球体などの単純な図形ではなく、より複雑な曲面
や多面体などの3Dの形状を描くにはどうすれば良いのか?

‣

ポリゴンメッシュ (Polygon Mesh) を使用する

‣

op...
メッシュ (頂点情報の集合) - ofMesh
‣

メッシュによって構成された複雑な形状の例
メッシュ (頂点情報の集合) - ofMesh
‣

メッシュ (ポリゴンメッシュ Polygon Mesh)

‣

3Dグラフィックのモデリングの多面体オブジェクトの形
状を定義する頂点、辺、面の集合のこと

‣

通常は三角形や四角形のポ...
メッシュ (頂点情報の集合) - ofMesh
‣

sin関数を利用して波を生成し、その3Dの形態をメッシュ
で表現してみる

‣

まず、x, y軸方向に均等に並ぶグリッドを作成

‣

グリッドの頂点をそれぞれ、x軸、y軸で異なる周波数の...
メッシュ (頂点情報の集合) - ofMesh
‣

testApp.h

#pragma once

!

#include "ofMain.h"

!

class testApp : public ofBaseApp{
public:
v...
メッシュ (頂点情報の集合) - ofMesh
‣

testApp.cpp

#include "testApp.h"

!

void testApp::setup(){
// 画面の設定
ofBackground(0);
ofEnable...
メッシュ (頂点情報の集合) - ofMesh
‣

testApp.cpp

void testApp::update(){
// まず全ての頂点情報を削除
mesh.clearVertices();
// 全ての頂点の位置を更新して頂点情報...
メッシュ (頂点情報の集合) - ofMesh
‣

testApp.cpp

void testApp::draw(){
// メッシュの描画
ofSetHexColor(0xffffff);
cam.begin(); // カメラ開始
//...
メッシュ (頂点情報の集合) - ofMesh
‣

完成!!
VBO (頂点バッファオブジェクト)
ofVBO
VBO (頂点バッファオブジェクト) - ofVBO
‣

ポリゴンメッシュなどの複雑な3D形状

‣

大量の頂点の情報を高速に演算する必要がある

‣

CPUに高負荷な演算
!

‣

VBO (頂点バッファオブジェクト)

‣

あらか...
VBO (頂点バッファオブジェクト) - ofVBO
‣

VBOのイメージ
GPU

大量の頂点
座標情報

高速演算

大量の頂点
色情報

CPU
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.h

#pragma once

!

#include "ofMain.h"

!

class testApp : public ofBaseApp{
public...
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.cpp

#include "testApp.h"

!

const int testApp::WIDTH;
const int testApp::HEIGHT;
c...
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.cpp

void testApp::update(){
// 頂点の座標を更新
for (int i = 0; i < WIDTH; i++) {
for (int ...
VBO (頂点バッファオブジェクト) - ofVBO
‣

完成!!
VBO 応用
カメラの明度でメッシュを生成
カメラの明度でメッシュを生成
‣

VBO + Mesh、応用

‣

カメラから映像を入力

‣

映像のそれぞれのピクセルの明さを頂点の高さに

‣

ビデオからの色を、頂点の色に
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.h

#pragma once

!

#include "ofMain.h"

!

class testApp : public ofBaseApp{
public...
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.cpp

#include "testApp.h"

!

const int testApp::WIDTH;
const int testApp::HEIGHT;
c...
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.cpp

void testApp::update(){
// カメラからの映像を更新
myVideo.update();
// もしカメラのフレームが更新されていたら...
VBO (頂点バッファオブジェクト) - ofVBO
‣

testApp.cpp

void testApp::draw(){
// VBOを描画
cam.begin();
ofScale(1, -1, 1);
glPointSize(3);...
カメラの明度でメッシュを生成
‣

完成!!
VBO (頂点バッファオブジェクト) - ofVBO
‣

よりVBOのパワーを実感できるサンプル

‣

大量のパーティクルをnoise関数で飛散させる

‣

それぞれのパーティクルにはテクスチャ画像を貼る

‣

高速にアニメーションして...
VBO (頂点バッファオブジェクト) - ofVBO
‣

大量のパーティクルを高速にアニメーション
Upcoming SlideShare
Loading in...5
×

Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL

15,034

Published on

Published in: Technology, Art & Photos
0 Comments
21 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
15,034
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
119
Comments
0
Likes
21
Embeds 0
No embeds

No notes for slide

Transcript of "Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL"

  1. 1. Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL 多摩美術大学情報デザイン学科メディア芸術コース 2013年10月28日 田所 淳
  2. 2. 今日の内容 ‣ openFrameworksの、3D機能、OpenGLの機能を中心に 取り上げます
  3. 3. 今日の内容 ‣ 3DやOpenGLに関する機能を概観します クラス名 機能 ofBox, ofSphere 3Dプリミティブオブジェクトの描画 ofEasyCam 簡単に利用可能なカメラ(視点)機能 ofLight ライティング効果 ofMesh 3D物体の全ての頂点情報を持ったデータ ofVBO 3Dシーンの物体の情報(位置・色)の保存 ofShader プログラマブルシェーダ
  4. 4. 3Dプリミティブ図形の描画 ofBox、ofSphere
  5. 5. 3Dプリミティブ図形の描画 ofBox、ofSphere ‣ openFrameworks v080から、3Dの基本図形の描き方が 変化 ! ‣ 球体: ofSphere → ofSpherePrimtive ‣ 立方体: ofBox → ofBoxPrimitive ! ‣ ofRectやofCircleのように、testApp::draw() 関数内に記 述して座標とサイズを指定するだけで簡単に利用可能
  6. 6. 3Dプリミティブ図形の描画 ofBox、ofSphere ‣ testApp.h #pragma once ! #include "ofMain.h" ! class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void void void void void void void void void keyPressed(int key); keyReleased(int key); mouseMoved(int x, int y); mouseDragged(int x, int y, int button); mousePressed(int x, int y, int button); mouseReleased(int x, int y, int button); windowResized(int w, int h); dragEvent(ofDragInfo dragInfo); gotMessage(ofMessage msg); ofBoxPrimitive box; // 立方体プリミティブ ofSpherePrimitive sphere; // 球プリミティブ };
  7. 7. 3Dプリミティブ図形の描画 ofBox、ofSphere ‣ testApp.cpp #include "testApp.h" ! void testApp::setup(){ ofBackground(0); } ! void testApp::update(){ } ! void testApp::draw(){ ofTranslate(ofGetWidth()/2, ofGetHeight()/2); ofSetColor(255); // 立方体 box.set(200); // サイズ設定 box.setPosition(-150, 0, 0); // 位置 box.drawWireframe(); // ワイヤーフレームを描画 // 球 sphere.set(100, 16); // 半径と面の細かさ sphere.setPosition(150, 0, 0); // 位置 sphere.drawWireframe(); // ワイヤーフレームを描画 }
  8. 8. 3Dプリミティブ図形の描画 ofBox、ofSphere ‣ 完成!!
  9. 9. 視点をインタラクティブに移動 ofEasyCam
  10. 10. 視点をインタラクティブに移動 - ofEasyCam ‣ 次に、この図形を様々な角度から眺められるようにする ‣ 物体を動かすのではなく、視点(カメラ)を移動して、物体 を注視する角度を変更してみる ‣ 視点を指定するofEasyCamというクラスがあり、とても 簡単に視点の移動が可能 ‣ より詳細な視点や画角などの指定には、ofCameraという クラスもある
  11. 11. 視点をインタラクティブに移動 - ofEasyCam ‣ testApp.h #pragma once ! #include "ofMain.h" ! class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void void void void void void void void void keyPressed(int key); keyReleased(int key); mouseMoved(int x, int y); mouseDragged(int x, int y, int button); mousePressed(int x, int y, int button); mouseReleased(int x, int y, int button); windowResized(int w, int h); dragEvent(ofDragInfo dragInfo); gotMessage(ofMessage msg); ofBoxPrimitive box; // 立方体プリミティブ ofSpherePrimitive sphere; // 球プリミティブ ofEasyCam cam; // カメラ };
  12. 12. 視点をインタラクティブに移動 - ofEasyCam ‣ testApp.cpp … (前略) … ! void testApp::draw(){ cam.begin(); // カメラ開始 ofSetColor(255); // 立方体 box.set(200); // サイズ設定 box.setPosition(-150, 0, 0); // 位置 box.drawWireframe(); // ワイヤーフレームを描画 // 球 sphere.set(100, 16); // 半径と面の細かさ sphere.setPosition(150, 0, 0); // 位置 sphere.drawWireframe(); // ワイヤーフレームを描画 cam.end(); // カメラ終了 }
  13. 13. 視点をインタラクティブに移動 - ofEasyCam ‣ testApp.cpp … (前略) … ! void testApp::draw(){ cam.begin(); // カメラ開始 ofSetColor(255); // 立方体 camera.begin( )と box.set(200); // サイズ設定 camera.end( )で囲まれた範囲 box.setPosition(-150, 0, 0); // 位置 が、マウスのドラッグで視点変 更可能となる box.drawWireframe(); // ワイヤーフレームを描画 // 球 sphere.set(100, 16); // 半径と面の細かさ sphere.setPosition(150, 0, 0); // 位置 sphere.drawWireframe(); // ワイヤーフレームを描画 cam.end(); // カメラ終了 }
  14. 14. 視点をインタラクティブに移動 - ofEasyCam ‣ マウスをドラッグすると物体を回転できる
  15. 15. ライティング ofLight
  16. 16. ライティング - ofLight ‣ プリミティブを描画する命令 ‣ ‣ ‣ プリミティブ.drawWireframe() → ワイヤーフレーム プリミティブ.draw() → 塗り潰し 実際にやってみる
  17. 17. ライティング - ofLight ‣ testApp.cpp void testApp::draw(){ cam.begin(); // カメラ開始 ofSetColor(255); // 立方体 box.set(200); // サイズ設定 box.setPosition(-150, 0, 0); // 位置 box.draw(); // 塗りつぶしで描画 ←ココ // 球 sphere.set(100, 16); // 半径と面の細かさ sphere.setPosition(150, 0, 0); // 位置 sphere.draw(); // 塗りつぶしで描画 cam.end(); // カメラ終了 } ←ココ
  18. 18. ライティング - ofLight ‣ 陰影も何もない、のっぺりとした図形になってしまう
  19. 19. ライティング - ofLight ‣ なぜ、陰影のないのっぺりとした図形になってしまうのか? ‣ ライティングがされていないから ‣ 適切な照明を物体に照射することで、リアルな陰影が表現 される ‣ ofLightクラスを使用する
  20. 20. ライティング - ofLight ‣ ofLightでは「Phongシェーディング」というアルゴリズ ムで、物体にリアルな陰影や反射を付加している ‣ 3Dグラフィックにおいて、モデリングされた面上の点に 影をつけるための照明と陰影モデル ‣ ユタ大学のBui Tuong Phongによって開発 (1973)
  21. 21. ライティング - ofLight ‣ Phongシェーディング ‣ 3つの光の反射の強度と色を指定する ‣ 鏡面反射 (Specular) ‣ 拡散反射 (Diffuse) ‣ 環境反射 (Ambient)
  22. 22. ライティング - ofLight ‣ testApp.h #pragma once ! #include "ofMain.h" ! class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void void void void void void void void void keyPressed(int key); keyReleased(int key); mouseMoved(int x, int y); mouseDragged(int x, int y, int button); mousePressed(int x, int y, int button); mouseReleased(int x, int y, int button); windowResized(int w, int h); dragEvent(ofDragInfo dragInfo); gotMessage(ofMessage msg); ofBoxPrimitive box; // 立方体プリミティブ ofSpherePrimitive sphere; // 球プリミティブ ofEasyCam cam; // カメラ ofLight light; // ライト };
  23. 23. ライティング - ofLight ‣ testApp.cpp … (前略) … ! void testApp::setup(){ ofBackground(0); // ライティングを有効に light.enable(); // スポットライトを配置 light.setSpotlight(); // 照明の位置 light.setPosition(-100, 100, 100); // 環境反射光の色 light.setAmbientColor(ofFloatColor(0.5, 0.2, 0.2, 1.0)); // 拡散反射光の色 light.setDiffuseColor(ofFloatColor(0.5, 0.5, 1.0)); // 鏡面反射光の色 light.setSpecularColor(ofFloatColor(1.0, 1.0, 1.0)); } ! … (後略) …
  24. 24. ライティング - ofLight ‣ 立体のの前後の重なりが、おかしい!?
  25. 25. ライティング - ofLight ‣ openFrameworksでは、そのままの設定では後から実行 した命令がどんどん上のレイヤーに描かれる ‣ 3Dの立体の場合、有り得ない重なりになることも ‣ DEPTH TEST (深度テスト) を有効にする必要があり ‣ ofEnableDepthTest() で有効になる
  26. 26. ライティング - ofLight ‣ testApp.cpp を修正 … (前略) … ! void testApp::setup(){ ofBackground(0); ofEnableDepthTest(); // 深度テストを有効に ofEnableSmoothing(); // 表示をスムースに ←ココ // ライティングを有効に light.enable(); // スポットライトを配置 light.setSpotlight(); // 照明の位置 light.setPosition(-100, 100, 100); // 環境反射光の色 light.setAmbientColor(ofFloatColor(0.5, 0.2, 0.2, 1.0)); // 拡散反射光の色 light.setDiffuseColor(ofFloatColor(0.5, 0.5, 1.0)); // 鏡面反射光の色 light.setSpecularColor(ofFloatColor(1.0, 1.0, 1.0)); } ! … (後略) …
  27. 27. ライティング - ofLight ‣ 正しい重なりに
  28. 28. メッシュ (頂点情報の集合) ofMesh
  29. 29. メッシュ (頂点情報の集合) - ofMesh ‣ 立方体や球体などの単純な図形ではなく、より複雑な曲面 や多面体などの3Dの形状を描くにはどうすれば良いのか? ‣ ポリゴンメッシュ (Polygon Mesh) を使用する ‣ openFrameworksでは、ofMeshクラスで生成できる
  30. 30. メッシュ (頂点情報の集合) - ofMesh ‣ メッシュによって構成された複雑な形状の例
  31. 31. メッシュ (頂点情報の集合) - ofMesh ‣ メッシュ (ポリゴンメッシュ Polygon Mesh) ‣ 3Dグラフィックのモデリングの多面体オブジェクトの形 状を定義する頂点、辺、面の集合のこと ‣ 通常は三角形や四角形のポリゴン(面)によって構成される
  32. 32. メッシュ (頂点情報の集合) - ofMesh ‣ sin関数を利用して波を生成し、その3Dの形態をメッシュ で表現してみる ‣ まず、x, y軸方向に均等に並ぶグリッドを作成 ‣ グリッドの頂点をそれぞれ、x軸、y軸で異なる周波数のsin 関数で上下に振動させる ‣ 頂点の座標を描画する
  33. 33. メッシュ (頂点情報の集合) - ofMesh ‣ testApp.h #pragma once ! #include "ofMain.h" ! class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void void void void void void void void void keyPressed(int key); keyReleased(int key); mouseMoved(int x, int y); mouseDragged(int x, int y, int button); mousePressed(int x, int y, int button); mouseReleased(int x, int y, int button); windowResized(int w, int h); dragEvent(ofDragInfo dragInfo); gotMessage(ofMessage msg); ofEasyCam cam; // カメラ ofMesh mesh; // 3Dメッシュ int w, h; // メッシュの幅と高さ };
  34. 34. メッシュ (頂点情報の集合) - ofMesh ‣ testApp.cpp #include "testApp.h" ! void testApp::setup(){ // 画面の設定 ofBackground(0); ofEnableDepthTest(); cam.setDistance(100); // メッシュの幅と高さ w = 200; h = 200; // 頂点の色を初期化 for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { mesh.addColor(ofFloatColor(0.5, 0.8, 1.0)); } } }
  35. 35. メッシュ (頂点情報の集合) - ofMesh ‣ testApp.cpp void testApp::update(){ // まず全ての頂点情報を削除 mesh.clearVertices(); // 全ての頂点の位置を更新して頂点情報として追加 for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { float x = sin(i * 0.1 + ofGetElapsedTimef())*10.0; float y = sin(j*0.15 + ofGetElapsedTimef()) * 10.0; float z = x + y; mesh.addVertex(ofVec3f(i - w/2, j - h/2, z)); } } }
  36. 36. メッシュ (頂点情報の集合) - ofMesh ‣ testApp.cpp void testApp::draw(){ // メッシュの描画 ofSetHexColor(0xffffff); cam.begin(); // カメラ開始 // 頂点の位置をドットで表示 glPointSize(2.0); glEnable(GL_POINT_SMOOTH); mesh.drawVertices(); cam.end(); // カメラ終了 // ログの表示 string info; info = "Vertex num = " + ofToString(w * h, 0) + "n"; info += "FPS = " + ofToString(ofGetFrameRate(), 2); ofDrawBitmapString(info, 30, 30); }
  37. 37. メッシュ (頂点情報の集合) - ofMesh ‣ 完成!!
  38. 38. VBO (頂点バッファオブジェクト) ofVBO
  39. 39. VBO (頂点バッファオブジェクト) - ofVBO ‣ ポリゴンメッシュなどの複雑な3D形状 ‣ 大量の頂点の情報を高速に演算する必要がある ‣ CPUに高負荷な演算 ! ‣ VBO (頂点バッファオブジェクト) ‣ あらかじめ頂点データをOpenGL側に作成しておき、グラフィ クスカード側で演算を行う手法 ‣ CPUの負荷を減らし、高速な描画を実現する ! ‣ 先程ofMeshで作成した3Dの波を、ofVBOによる計算に変更し てみる
  40. 40. VBO (頂点バッファオブジェクト) - ofVBO ‣ VBOのイメージ GPU 大量の頂点 座標情報 高速演算 大量の頂点 色情報 CPU
  41. 41. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.h #pragma once ! #include "ofMain.h" ! class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); … (中略) … // クラス定数 static const int WIDTH = 200; static const int HEIGHT = 200; static const int NUM_PARTICLES = WIDTH * HEIGHT; ofEasyCam cam; // カメラ ofVbo myVbo; // VBO ofVec3f myVerts[NUM_PARTICLES]; // 頂点の座標 ofFloatColor myColor[NUM_PARTICLES]; // 頂点の色情報 };
  42. 42. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.cpp #include "testApp.h" ! const int testApp::WIDTH; const int testApp::HEIGHT; const int testApp::NUM_PARTICLES; ! void testApp::setup(){ // 画面の設定 ofBackground(0); ofEnableDepthTest(); ofEnableBlendMode(OF_BLENDMODE_ADD); cam.setDistance(100); // 頂点情報を初期化 for (int i = 0; i < for (int j = 0; myVerts[j * myColor[j * } } WIDTH; i++) { j < HEIGHT; j++) { WIDTH + i].set(i - WIDTH/2, j - HEIGHT/2, 0); WIDTH + i].set(0.5, 0.8, 1.0, 1.0); // 頂点バッファに位置と色の情報を設定 myVbo.setVertexData(myVerts, NUM_PARTICLES, GL_DYNAMIC_DRAW); myVbo.setColorData(myColor, NUM_PARTICLES, GL_DYNAMIC_DRAW); }
  43. 43. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.cpp void testApp::update(){ // 頂点の座標を更新 for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { float x = sin(i * 0.1 + ofGetElapsedTimef()) * 10.0; float y = sin(j * 0.15 + ofGetElapsedTimef()) * 10.0; float z = x + y; myVerts[j * WIDTH + i] = ofVec3f(i - WIDTH/2, j - HEIGHT/2, z); } } // 頂点バッファの頂点の座標情報を更新 myVbo.updateVertexData(myVerts, NUM_PARTICLES); } ! void testApp::draw(){ // VBOの頂点を描画 cam.begin(); glPointSize(2); myVbo.draw(GL_POINTS, 0, NUM_PARTICLES); cam.end(); // ログの表示 string info; info = "Vertex num = " + ofToString(NUM_PARTICLES, 0) + "n"; info += "FPS = " + ofToString(ofGetFrameRate(), 2); ofDrawBitmapString(info, 30, 30); }
  44. 44. VBO (頂点バッファオブジェクト) - ofVBO ‣ 完成!!
  45. 45. VBO 応用 カメラの明度でメッシュを生成
  46. 46. カメラの明度でメッシュを生成 ‣ VBO + Mesh、応用 ‣ カメラから映像を入力 ‣ 映像のそれぞれのピクセルの明さを頂点の高さに ‣ ビデオからの色を、頂点の色に
  47. 47. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.h #pragma once ! #include "ofMain.h" ! class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); … (中略) … // クラス定数 static const int WIDTH = 640; static const int HEIGHT = 480; static const int NUM_PARTICLES = WIDTH * HEIGHT; ofEasyCam cam; // カメラ ofLight light; // ライト ofVbo myVbo; // VBO ofVec3f myVerts[NUM_PARTICLES]; // 頂点の座標 ofFloatColor myColor[NUM_PARTICLES]; // 頂点の色情報 ofVideoGrabber myVideo; }; // ビデオキャプチャ
  48. 48. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.cpp #include "testApp.h" ! const int testApp::WIDTH; const int testApp::HEIGHT; const int testApp::NUM_PARTICLES; ! void testApp::setup(){ // 画面の設定 ofBackground(0); ofEnableDepthTest(); ofEnableBlendMode(OF_BLENDMODE_ADD); cam.setDistance(400); myVideo.initGrabber(640, 480); // カメラ映像をキャプチャ ! // 頂点情報を初期化 for (int i = 0; i < for (int j = 0; myVerts[j * myColor[j * } } WIDTH; i++) { j < HEIGHT; j++) { WIDTH + i].set(i - WIDTH/2, j - HEIGHT/2, 0); WIDTH + i].set(1.0, 1.0, 1.0, 1.0); // 頂点バッファに位置と色の情報を設定 myVbo.setVertexData(myVerts, NUM_PARTICLES, GL_DYNAMIC_DRAW); myVbo.setColorData(myColor, NUM_PARTICLES, GL_DYNAMIC_DRAW); }
  49. 49. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.cpp void testApp::update(){ // カメラからの映像を更新 myVideo.update(); // もしカメラのフレームが更新されていたら if (myVideo.isFrameNew()) { // カメラの映像のピクセル情報を抽出 unsigned char * pixels = myVideo.getPixels(); // ピクセルごとに処理 for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { // ピクセルノRGB値を取得 float r = (float)pixels[j * myVideo.width * 3 + i * 3] / 256.0; float g = (float)pixels[j * myVideo.width * 3 + i * 3 + 1] / 256.0; float b = (float)pixels[j * myVideo.width * 3 + i * 3 + 2] / 256.0; // RGBから明度を算出 float brightness = (r + g + b) / 3.0f; // 明度から頂点の位置を設定 myVerts[j * WIDTH + i] = ofVec3f(i - WIDTH/2, j - HEIGHT/2, brightness * 256.0); // 頂点の色はカメラのピクセルの値をそのまま使用 } myColor[j * WIDTH + i] = ofFloatColor(r, g, b, 0.8); } // VBOの座標と色の情報を更新 } } myVbo.updateVertexData(myVerts, NUM_PARTICLES); myVbo.updateColorData(myColor, NUM_PARTICLES);
  50. 50. VBO (頂点バッファオブジェクト) - ofVBO ‣ testApp.cpp void testApp::draw(){ // VBOを描画 cam.begin(); ofScale(1, -1, 1); glPointSize(3); myVbo.draw(GL_POINTS, 0, NUM_PARTICLES); cam.end(); // ログの表示 string info; info = "Vertex num = " + ofToString(NUM_PARTICLES, 0) + "n"; info += "FPS = " + ofToString(ofGetFrameRate(), 2); ofDrawBitmapString(info, 30, 30); }
  51. 51. カメラの明度でメッシュを生成 ‣ 完成!!
  52. 52. VBO (頂点バッファオブジェクト) - ofVBO ‣ よりVBOのパワーを実感できるサンプル ‣ 大量のパーティクルをnoise関数で飛散させる ‣ それぞれのパーティクルにはテクスチャ画像を貼る ‣ 高速にアニメーションしてみる
  53. 53. VBO (頂点バッファオブジェクト) - ofVBO ‣ 大量のパーティクルを高速にアニメーション
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×