Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
ゲームグラフィックス特論
第13回 遅延レンダリング
Render To Texture
テクスチャにレンダリング
2
レンダリング結果を素材として利⽤する
• 映り込みや屈折などの光学的効果
1. 視点を変更してレンダリングする
2. レンダリング結果をテクスチャとしてマッピングする
• このレンダリング結果は直接には画⾯に表⽰されない
• 素材を作成するため...
フレームバッファオブジェクト
• 標準のフレームバッファ
• あらかじめ⽤意されている
• 描き込んだ図形はディスプレイに表⽰される
• フレームバッファオブジェクト
• Frame Buffer Object, FBO
• ユーザが⾃分で⽤意...
フレームバッファオブジェクトの作成
• フレームバッファは複数のバッファの集合体
• カラーバッファ(⾊)
• デプスバッファ(深度)
• ステンシルバッファ(型抜き)
• それぞれのバッファとして使うメモリを確保する
• テクスチャにより確保...
カラーバッファ⽤テクスチャの確保
#define FBOWIDTH 512 // フレームバッファオブジェクトの幅
#define FBOHEIGHT 512 // フレームバッファオブジェクトの⾼さ
…
GLuint cb; // カラーバッ...
デプスバッファ⽤テクスチャの確保
Gluint db; // デプスバッファ⽤のテクスチャ名
…
// デプスバッファ⽤のテクスチャを⽤意する
glGenTextures(1, &db);
glBindTexture(GL_TEXTURE_2D...
フレームバッファオブジェクトの作成
// フレームバッファオブジェクトを作成する
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// カラーバッファとしてテク...
レンダーバッファをデプスバッファに使う
Gluint rb; // デプスバッファ⽤のレンダーバッファ名
…
// デプスバッファ⽤のレンダーバッファを⽤意する
glGenRenderbuffers(1, &rb);
glBindRenderb...
フレームバッファオブジェクトの作成
// フレームバッファオブジェクトを作成する
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// カラーバッファとしてテク...
カラーバッファを使わない場合
// フレームバッファオブジェクトを作成する
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// フレームバッファオブジェクトに...
フレームバッファオブジェクトへの描画
// フレームバッファオブジェクトを結合する
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// ビューポートはフレームバッファオブジェクトのサイズ以下にする
glViewp...
応⽤例
FBO の使い⽅の実例
13
応⽤例
シャドウマッピング 映り込み処理
14
シャドウマッピング
1. フレームバッファオブジェクトを作成する
• カラーバッファは⽤いない/読み書きしない
• デプスバッファはテクスチャ(デプスマップ)
2. 描画先をフレームバッファオブジェクトに切り替える
3. 光源側から⾒たシーンを...
映り込み処理 (宿題のヒントに実装例)
1. フレームバッファオブジェクトを作成する
• カラーバッファはテクスチャ
• デプスバッファはレンダーバッファ
2. 描画先をフレームバッファオブジェクトに切り替える
3. 図形の鏡像をフレームバッフ...
Multiple Render Target
⼀度に複数の画像を⽣成する
17
マルチプルレンダーターゲット
• フレームバッファオブジェクト
• カラーバッファを複数持たせることができる
• マルチプルレンダーターゲット
• フラグメントシェーダが同時に複数のカラーバッファに描き込む機能
• 最終的なレンダリング結果は複...
複数のカラーバッファの準備
GLint cb, sb, ab;
…
// 拡散反射光を格納するテクスチャを⽤意する
glGenTextures(1, &cb);
glBindTexture(GL_TEXTURE_2D, cb);
glTexIm...
フレームバッファオブジェクトの作成
// フレームバッファオブジェクトを作成
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// フレームバッファオブジェクト...
レンダーターゲット
/*
** レンダーターゲットのリスト
*/
const GLenum bufs[] =
{
GL_COLOR_ATTACHMENT0, // カラーバッファ (拡散反射光)
GL_COLOR_ATTACHMENT1, //...
レンダーターゲットの指定
// フレームバッファオブジェクトを結合する
glBindFramebuffer(GL_FRAMEBUFFER, fb);
// レンダーターゲットを指定する
glDrawBuffers(sizeof bufs / s...
フラグメントシェーダの例
#version 150 core
#extension GL_ARB_explicit_attrib_location : enable
…
in vec4 iamb; // 環境光の反射光 A
in vec4 id...
24
法線ベクトル 放射照度マップ 深度
放射照度 環境遮蔽
環境遮蔽を考慮した
放射照度
MRT を使った
遅延レンダリング
25
環境遮蔽を考慮した
放射照度
アルベド
拡散反射光強度
環境マップ視線の反射ベクトル
映り込みフレネル係数
合成結果
Post Processing Effect
画像処理による映像効果
26
遅延レンダリング
• ある種の映像効果はレンダリング後に適⽤する
• Screen Space Ambient Occlusion (SSAO)
• グロー効果・ブルーム効果
• モーションブラー
• Motion Blur as a Post...
残光エフェクト
28
(デザイン情報学科15期 篠原史典⽒)
Screen Space Motion Blur
29
遅延レンダリングの⼿順
• テクスチャメモリに画像を⽤意する
• 画像の読み込み
• Render To Texture
• Multiple Render Target
• クリッピング空間を覆う1枚のポリゴンを描く
• バーテックスシェーダ...
通常のフレームバッファへに切り替える
…
// フレームバッファオブジェクトの結合を解除する
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// レンダーターゲットを元に戻す
glDrawBuffer(GL_BAC...
1枚のポリゴンを描く
// クリッピング空間いっぱいの矩形ポリゴン
static const GLfloat pv[][2] = {
{ -1.0f, -1.0f },
{ 1.0f, -1.0f },
{ 1.0f, 1.0f },
{ -1...
バーテックスシェーダ
#version 150 core
in vec2 pv; // 矩形の頂点位置
out vec2 tc; // フラグメントシェーダに送るテクスチャ座標
void main()
{
tc = pv * 0.5 + 0.5...
フラグメントシェーダの例
#version 150 core
uniform sampler2D diffuse; // 拡散反射光のテクスチャユニット
uniform sampler2D specular; // 鏡⾯反射光のテクスチャユニッ...
輪郭強調フィルタ(4近傍)
#version 150 core
uniform sampler2D diffuse; // 拡散反射光のテクスチャユニット
uniform sampler2D specular; // 鏡⾯反射光のテクスチャユニ...
宿題
• FBO を使って平⾯への映り込み処理を実装してください.
• 次のプログラムは市松模様のついた平⾯の上を物体が移動します.
• https://github.com/tokoik/ggsample13
• この市松模様のついた平⾯に物...
宿題プログラムの⽣成画像
元のプログラム 期待する結果
37
映り込み処理の実装のヒント
• 鏡像は元のオブジェクトの上下 (y 軸) を反転します
• これによりポリゴンの表裏が反転しますので,正しく陰影付けするに
は法線ベクトルを反転する必要があります
• simple.vert をコピーして鏡像⽤の...
カラーバッファのテクスチャの作成
// フレームバッファオブジェクトの解像度
const GLsizei fboWidth(1024), fboHeight(1024);
// カラーバッファ⽤のテクスチャを⽤意する
GLuint cb;
gl...
レンダーバッファの作成
// デプスバッファ⽤のレンダーバッファを⽤意する
GLuint rb;
glGenRenderbuffers(1, &rb);
glBindRenderbuffer(GL_RENDERBUFFER, rb);
glRe...
フレームバッファオブジェクトの作成
// 映り込み⽤のフレームバッファオブジェクトを作成する
GLuint fb;
glGenFramebuffers(1, &fb);
glBindFramebuffer(GL_FRAMEBUFFER, fb)...
鏡像の変換⾏列とその光源位置を求める
// 正像のビュー変換⾏列を mv に求める
const GgMatrix mv(ggLookat(0.0f, 3.0f, 8.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f)...
FBO にレンダリング開始
// ビューポートをフレームバッファオブジェクトのサイズに合わせる
glViewport(0, 0, fboWidth, fboHeight);
// フレームバッファオブジェクトを結合する
glBindFrameb...
FBO に鏡像をレンダリング
// 前⾯をカリングする
glCullFace(GL_FRONT);
// 鏡像をフレームバッファオブジェクトに描画
drawObjects(mirror, mp, mr, object.get(), object...
床⾯はカラーテクスチャを参照して描画
// 床⾯の描画
ground.loadMaterial(tile);
ground.loadMatrix(mp, mv.rotateX(-1.5707963f));
glActiveTexture(GL_...
拡張課題
映り込みをぼかす さらに影を追加する
46
Upcoming SlideShare
Loading in …5
×

ゲームグラフィックス特論 第13回

3,600 views

Published on

Frame Buffer Object, Render To Texture, Multiple Render Target, Deferred Rendering

Published in: Education
  • Be the first to comment

ゲームグラフィックス特論 第13回

  1. 1. ゲームグラフィックス特論 第13回 遅延レンダリング
  2. 2. Render To Texture テクスチャにレンダリング 2
  3. 3. レンダリング結果を素材として利⽤する • 映り込みや屈折などの光学的効果 1. 視点を変更してレンダリングする 2. レンダリング結果をテクスチャとしてマッピングする • このレンダリング結果は直接には画⾯に表⽰されない • 素材を作成するために画⾯表⽰を⾏わずにレンダリングする • オフスクリーンレンダリング • かつては • フレームバッファの表⽰領域外 • ダブルバッファリング時のバックバッファ,など • レンダリング結果をテクスチャメモリに転送する必要がある 3
  4. 4. フレームバッファオブジェクト • 標準のフレームバッファ • あらかじめ⽤意されている • 描き込んだ図形はディスプレイに表⽰される • フレームバッファオブジェクト • Frame Buffer Object, FBO • ユーザが⾃分で⽤意する • 図形を描き込んでもディスプレイには表⽰されない • テクスチャとして直接参照できる • FBO を使えばテクスチャメモリに直接レンダリングできる 4 Render To Texture
  5. 5. フレームバッファオブジェクトの作成 • フレームバッファは複数のバッファの集合体 • カラーバッファ(⾊) • デプスバッファ(深度) • ステンシルバッファ(型抜き) • それぞれのバッファとして使うメモリを確保する • テクスチャにより確保する • レンダリング結果をテクスチャとして利⽤する場合 • レンダーバッファにより確保する • レンダリング結果をテクスチャとして利⽤しない場合 • 確保したメモリを組み合わせてフレームバッファを構成する • 使わないバッファのメモリは準備する必要は無い • 準備しないバッファへの読み書きは禁⽌しておく 5
  6. 6. カラーバッファ⽤テクスチャの確保 #define FBOWIDTH 512 // フレームバッファオブジェクトの幅 #define FBOHEIGHT 512 // フレームバッファオブジェクトの⾼さ … GLuint cb; // カラーバッファ⽤のテクスチャ名 … glGenTextures(1, &cb); glBindTexture(GL_TEXTURE_2D, cb); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, FBOWIDTH, FBOHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); …(その他のテクスチャ設定) glBindTexture(GL_TEXTURE_2D, 0); 6 レンダリングによって書き込むので ここで画像を読み込む必要は無い GL_RGBAだと [0,1] にクランプされる GL_RGBA32F なら実数(単精度)が使 える(浮動⼩数点テクスチャ) これは多分どうでもいい
  7. 7. デプスバッファ⽤テクスチャの確保 Gluint db; // デプスバッファ⽤のテクスチャ名 … // デプスバッファ⽤のテクスチャを⽤意する glGenTextures(1, &db); glBindTexture(GL_TEXTURE_2D, db); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, FBOWIDTH, FBOHEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr); …(その他のテクスチャ設定) glBindTexture(GL_TEXTURE_2D, 0); 7 デプスバッファなので これも多分どうでもいい
  8. 8. フレームバッファオブジェクトの作成 // フレームバッファオブジェクトを作成する glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); // カラーバッファとしてテクスチャを結合する glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cb, 0); // デプスバッファとしてテクスチャを結合する glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, db, 0); // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); 8
  9. 9. レンダーバッファをデプスバッファに使う Gluint rb; // デプスバッファ⽤のレンダーバッファ名 … // デプスバッファ⽤のレンダーバッファを⽤意する glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, FBOWIDTH, FBOHEIGHT); // レンダーバッファの結合を解除する glBindRenderbuffer(GL_RENDERBUFFER, 0); 9
  10. 10. フレームバッファオブジェクトの作成 // フレームバッファオブジェクトを作成する glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); // カラーバッファとしてテクスチャを結合する glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cb, 0); // デプスバッファとしてレンダーバッファを結合する glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb); // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); 10
  11. 11. カラーバッファを使わない場合 // フレームバッファオブジェクトを作成する glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); // フレームバッファオブジェクトにデプスバッファのテクスチャを結合する glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, db, 0); // カラーバッファは無いので読み書きしない glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); 11 シャドウマッピングに使う デプステクスチャ作成など
  12. 12. フレームバッファオブジェクトへの描画 // フレームバッファオブジェクトを結合する glBindFramebuffer(GL_FRAMEBUFFER, fb); // ビューポートはフレームバッファオブジェクトのサイズ以下にする glViewport(0, 0, FBOWIDTH, FBOHEIGHT); // シーンの描画 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); … glFlush(); // FBO への描き込み完了を待つなら glFinish(); // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); 12
  13. 13. 応⽤例 FBO の使い⽅の実例 13
  14. 14. 応⽤例 シャドウマッピング 映り込み処理 14
  15. 15. シャドウマッピング 1. フレームバッファオブジェクトを作成する • カラーバッファは⽤いない/読み書きしない • デプスバッファはテクスチャ(デプスマップ) 2. 描画先をフレームバッファオブジェクトに切り替える 3. 光源側から⾒たシーンを描く • 使⽤した投影変換⾏列とモデルビュー変換⾏列を保存しておく 4. 描画先を通常のフレームバファに戻す 5. 視点側から⾒たシーンを描く • テクスチャをデプスマップとしてマッピングする 15
  16. 16. 映り込み処理 (宿題のヒントに実装例) 1. フレームバッファオブジェクトを作成する • カラーバッファはテクスチャ • デプスバッファはレンダーバッファ 2. 描画先をフレームバッファオブジェクトに切り替える 3. 図形の鏡像をフレームバッファオブジェクトに描く 4. 描画先を通常のフレームバッファに戻す 5. 本来の図形を描く 6. 床を描く • フレームバッファオブジェクトのカラーバッファに使ったテクスチャ をマッピングする 16
  17. 17. Multiple Render Target ⼀度に複数の画像を⽣成する 17
  18. 18. マルチプルレンダーターゲット • フレームバッファオブジェクト • カラーバッファを複数持たせることができる • マルチプルレンダーターゲット • フラグメントシェーダが同時に複数のカラーバッファに描き込む機能 • 最終的なレンダリング結果は複数の画像を合成したもの • 環境光の反射光,拡散反射光,鏡⾯反射光 • 映り込み,透過光 • 物体表⾯の座標値,物体表⾯の法線ベクトル • 物体の識別⼦,材質の識別⼦ • … • マルチパスレンダリング • かつてはレンダリング結果をフレームバッファ上で合成していた 18 ⾊情報では ないもの 浮動⼩数点テクスチャ
  19. 19. 複数のカラーバッファの準備 GLint cb, sb, ab; … // 拡散反射光を格納するテクスチャを⽤意する glGenTextures(1, &cb); glBindTexture(GL_TEXTURE_2D, cb); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,(中略), nullptr); … // 鏡⾯反射光を格納するテクスチャを⽤意する glGenTextures(1, &sb); glBindTexture(GL_TEXTURE_2D, sb); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,(中略), nullptr); … // 環境光の反射光を格納するテクスチャを⽤意する glGenTextures(1, &ab); glBindTexture(GL_TEXTURE_2D, ab); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,(中略), nullptr); … glBindTexture(GL_TEXTURE_2D, 0); 19
  20. 20. フレームバッファオブジェクトの作成 // フレームバッファオブジェクトを作成 glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); // フレームバッファオブジェクトに拡散反射光の格納先のテクスチャを結合 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cb, 0); // フレームバッファオブジェクトに鏡⾯反射光の格納先のテクスチャを結合 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, sb, 0); // フレームバッファオブジェクトに環境光の反射光の格納先のテクスチャを結合 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, ab, 0); … // フレームバッファオブジェクトの結合を解除 glBindFramebuffer(GL_FRAMEBUFFER, 0); 20
  21. 21. レンダーターゲット /* ** レンダーターゲットのリスト */ const GLenum bufs[] = { GL_COLOR_ATTACHMENT0, // カラーバッファ (拡散反射光) GL_COLOR_ATTACHMENT1, // 鏡⾯反射光 GL_COLOR_ATTACHMENT2, // 環境光の反射光 }; 21 • デフォルトのフレームバッファ (GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK_LEFT, GL_BACK_RIGHT) と GL_COLOR_ATTACHMENTn と を混在して指定することはできない • 複数のバッファを表す GL_FRONT, GL_BACK, GL_LEFT, GL_RIGHT, GL_FRONT_AND_BACK を指定することはできない
  22. 22. レンダーターゲットの指定 // フレームバッファオブジェクトを結合する glBindFramebuffer(GL_FRAMEBUFFER, fb); // レンダーターゲットを指定する glDrawBuffers(sizeof bufs / sizeof bufs[0], bufs); // シーンの描画 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); … glFlush(); // レンダーターゲットを元に戻す glDrawBuffer(GL_BACK); // ダブルバッファリングのとき // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); 22 レンダーターゲットの数 (bufs の要素数)
  23. 23. フラグメントシェーダの例 #version 150 core #extension GL_ARB_explicit_attrib_location : enable … in vec4 iamb; // 環境光の反射光 A in vec4 idiff; // 拡散反射光 D in vec4 ispec; // 鏡⾯反射光 S out (layout = 0) vec4 diffuse; // bufs[0] に指定したバッファ out (layout = 1) vec4 specular; // bufs[1] に指定したバッファ out (layout = 2) vec4 ambient; // bufs[2] に指定したバッファ void main() { diffuse = idiff; specular = ispec; ambient = iamb; } 23 GLSL 3.3 (#version 330) 以降では不要
  24. 24. 24 法線ベクトル 放射照度マップ 深度 放射照度 環境遮蔽 環境遮蔽を考慮した 放射照度 MRT を使った 遅延レンダリング
  25. 25. 25 環境遮蔽を考慮した 放射照度 アルベド 拡散反射光強度 環境マップ視線の反射ベクトル 映り込みフレネル係数 合成結果
  26. 26. Post Processing Effect 画像処理による映像効果 26
  27. 27. 遅延レンダリング • ある種の映像効果はレンダリング後に適⽤する • Screen Space Ambient Occlusion (SSAO) • グロー効果・ブルーム効果 • モーションブラー • Motion Blur as a Post-Processing Effect (GPU Gems 3, Chapter 27) • ある種のアンチエリアシング⼿法 • Morphological Antialiasing (MLAA) • Reshetov, Alexander. "Morphological antialiasing." Proceedings of the Conference on High Performance Graphics 2009. ACM, 2009. • Fast Approximate Anti Aliasing (FXAA) • Lottes, T. "Fast approximate anti-aliasing." (2009). • Subpixel Morphological Antialiasing (SMAA) • Jimenez, Jorge, et al. "SMAA: Enhanced subpixel morphological antialiasing." Computer Graphics Forum. Vol. 31. No. 2pt1. Blackwell Publishing Ltd, 2012. • 複雑な光学効果による陰影を可視⾯に対してのみ⾏う • デプスバッファ法による隠⾯消去処理で捨てられてしまう無駄を避ける 27
  28. 28. 残光エフェクト 28 (デザイン情報学科15期 篠原史典⽒)
  29. 29. Screen Space Motion Blur 29
  30. 30. 遅延レンダリングの⼿順 • テクスチャメモリに画像を⽤意する • 画像の読み込み • Render To Texture • Multiple Render Target • クリッピング空間を覆う1枚のポリゴンを描く • バーテックスシェーダ • ほとんど何もしない • クリッピング座標 (-1, -1)-(1, 1) からテクスチャ座標 (0, 0)-(1, 1) を⽣ 成する • フラグメントシェーダ • バーテックスシェーダから渡されたテクスチャ座標でテクスチャをサンプ リングして画像処理を⾏う 30
  31. 31. 通常のフレームバッファへに切り替える … // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); // レンダーターゲットを元に戻す glDrawBuffer(GL_BACK); // シングルバッファリングなら GL_FRONT // ビューポートを表⽰領域のサイズに合わせる glViewport(0, 0, width, height); // 隠⾯消去処理は⾏わない glDisable(GL_DEPTH_TEST); 31 先に保存しておくか OS あるいは ウィンドウシステムから取得する
  32. 32. 1枚のポリゴンを描く // クリッピング空間いっぱいの矩形ポリゴン static const GLfloat pv[][2] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { 1.0f, 1.0f }, { -1.0f, 1.0f }, }; // 表⽰領域を覆うポリゴンを描く GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(vbo); glBufferData(GL_ARRAY_BUFFER, sizeof pv, pv, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); glDrawArrays(GL_TRIANGLE_FAN, 0, sizeof pv / sizeof pv[0]); 32
  33. 33. バーテックスシェーダ #version 150 core in vec2 pv; // 矩形の頂点位置 out vec2 tc; // フラグメントシェーダに送るテクスチャ座標 void main() { tc = pv * 0.5 + 0.5; // (-1,-1)-(1,1)→(0,0)-(1,1)の変換 gl_Position = vec4(pv, 0.0, 1.0); } 33
  34. 34. フラグメントシェーダの例 #version 150 core uniform sampler2D diffuse; // 拡散反射光のテクスチャユニット uniform sampler2D specular; // 鏡⾯反射光のテクスチャユニット uniform sampler2D ambient; // 環境光のテクスチャユニット in vec2 tc; // 補間されたテクスチャ座標 out vec4 fc; // フラグメントの⾊ void main() { vec4 d = texture(diffuse, tc); vec4 s = texture(specular, tc); vec4 a = texture(ambient, tc); fc = d + s + a; // ⾜してるだけ } 34
  35. 35. 輪郭強調フィルタ(4近傍) #version 150 core uniform sampler2D diffuse; // 拡散反射光のテクスチャユニット uniform sampler2D specular; // 鏡⾯反射光のテクスチャユニット uniform sampler2D ambient; // 環境光のテクスチャユニット in vec2 tc; // 補間されたテクスチャ座標 out vec4 fc; // フラグメントの⾊ void main() { vec4 d = (texture(diffuse, tc) * 5.0 - textureOffset(diffuse, tc, ivec2( 0, -1)) - textureOffset(diffuse, tc, ivec2(-1, 0)) - textureOffset(diffuse, tc, ivec2( 1, 0)) - textureOffset(diffuse, tc, ivec2( 0, 1))) * 0.25; fc = d + texture(specular, tc) + texture2d(ambient, tc); } 35 0 -1 0 -1 5 -1 0 -1 0
  36. 36. 宿題 • FBO を使って平⾯への映り込み処理を実装してください. • 次のプログラムは市松模様のついた平⾯の上を物体が移動します. • https://github.com/tokoik/ggsample13 • この市松模様のついた平⾯に物体が映り込むようにしてください. • さらに,この映り込みをぼかしてください. • 根性があったら物体の影が平⾯上に落ちるようにしてください. • 影はシャドウマップ法を使って実現してください. • シャドウマップ法にも FBO を使ってください. • プログラムの各所を調べればヒントがあるかもしれません. • 変更するのは main.cpp と tile.vert / tile.frag だけです(多分). • main.cpp と tile.frag をメールに添付してください. • 送り先 tokoi@sys.wakayama-u.ac.jp 36
  37. 37. 宿題プログラムの⽣成画像 元のプログラム 期待する結果 37
  38. 38. 映り込み処理の実装のヒント • 鏡像は元のオブジェクトの上下 (y 軸) を反転します • これによりポリゴンの表裏が反転しますので,正しく陰影付けするに は法線ベクトルを反転する必要があります • simple.vert をコピーして鏡像⽤のバーテックスシェーダ mirror.vert を作成し,法線ベクトル n を反転する(負号をつける) • 背⾯カリングも反転(表⾯をカリング)します 38 // 正像⽤のプログラムオブジェクト GgSimpleShader simple("simple.vert", "simple.frag"); // 鏡像⽤のプログラムオブジェクト GgSimpleShader mirror("mirror.vert", "simple.frag"); glCullFace(GL_FRONT); max(dot(n, l), 0.0) を abs(dot(n, l)) にすれば simple.vert と共⽤にできるけど…
  39. 39. カラーバッファのテクスチャの作成 // フレームバッファオブジェクトの解像度 const GLsizei fboWidth(1024), fboHeight(1024); // カラーバッファ⽤のテクスチャを⽤意する GLuint cb; glGenTextures(1, &cb); glBindTexture(GL_TEXTURE_2D, cb); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fboWidth, fboHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 39 この場合はウィンドウのサイズを気にしなくてよい
  40. 40. レンダーバッファの作成 // デプスバッファ⽤のレンダーバッファを⽤意する GLuint rb; glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fboWidth, fboHeight); 40
  41. 41. フレームバッファオブジェクトの作成 // 映り込み⽤のフレームバッファオブジェクトを作成する GLuint fb; glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); // FBO のカラーバッファにテクスチャを取り付ける glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cb, 0); // FBO のデプスバッファにレンダーバッファを取り付ける glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb); 41
  42. 42. 鏡像の変換⾏列とその光源位置を求める // 正像のビュー変換⾏列を mv に求める const GgMatrix mv(ggLookat(0.0f, 3.0f, 8.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f)); // 視点座標系の光源位置を求める mv.projection(light.position, lp); // 鏡像のビュー変換⾏列を mr に求める const GgMatrix mr(mv * ggScale(1.0f, -1.0f, 1.0f)); // 鏡像の視点座標系における光源位置 GLfloat reflected[4]; mr.projection(reflected, lp); 42
  43. 43. FBO にレンダリング開始 // ビューポートをフレームバッファオブジェクトのサイズに合わせる glViewport(0, 0, fboWidth, fboHeight); // フレームバッファオブジェクトを結合する glBindFramebuffer(GL_FRAMEBUFFER, fb); // フレームバッファオブジェクトの画⾯消去 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 鏡像⽤のシェーダの選択 mirror.use(); mirror.loadLightMaterial(light); mirror.loadLightPosition(reflected); 43
  44. 44. FBO に鏡像をレンダリング // 前⾯をカリングする glCullFace(GL_FRONT); // 鏡像をフレームバッファオブジェクトに描画 drawObjects(mirror, mp, mr, object.get(), objects, t); // 背⾯のカリングに戻す glCullFace(GL_BACK); // フレームバッファオブジェクトの結合を解除する glBindFramebuffer(GL_FRAMEBUFFER, 0); // ビューポートをウィンドウのサイズに戻す glViewport(0, 0, window.getWidth(), window.getHeight()); 44 以降で正像の描画
  45. 45. 床⾯はカラーテクスチャを参照して描画 // 床⾯の描画 ground.loadMaterial(tile); ground.loadMatrix(mp, mv.rotateX(-1.5707963f)); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, cb); rectangle->draw(); 45
  46. 46. 拡張課題 映り込みをぼかす さらに影を追加する 46

×