8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Modern OpenGLAdvent Calendar 2017

Day 24

RaymarchingとGeometryを同一シーンにレンダーする

Last updated at Posted at 2018-04-05

 やることは非常に単純で、シェーダー側(gl_FragDepth)でデプスを更新することである。

ModernOpenGL-AdventCal2017/21-render_raymarching_and_geometory_at_the_same_time

Feature

  • GBuffer生成し、1パス目でGeometryをレンダーし、2パス目でRaymarchingをレンダーする
  • 2パス目のRaymarchingで、1パス目と同じカメラ情報で、rayを定義する
  • rayの衝突判定からシーンの深度を構築し、その値でgl_FragDepthを更新する

GBuffer生成

GBufferは、特に変な設定はしない。
位置、法線、色(アルベド)をカラーバッファ、デプスバッファをレンダーバッファとして生成する。(ofFboではデフォルトで、レンダーバッファがデプスバッファになる)


    vector<GLint> formats = { GL_RGBA16F, GL_RGBA16F, GL_RGBA16F };
    ofFbo::Settings settings;
    settings.width = WIDTH;
    settings.height = HEIGHT;
    settings.textureTarget = GL_TEXTURE_2D;
    settings.wrapModeHorizontal = GL_CLAMP_TO_EDGE;
    settings.wrapModeVertical = GL_CLAMP_TO_EDGE;
    settings.minFilter = GL_NEAREST;
    settings.maxFilter = GL_NEAREST;
    settings.numColorbuffers = 3;
    settings.colorFormats = formats;
    settings.numSamples = 4;
    settings.useDepth = true;
    settings.useStencil = true;
    
    g_buffer.allocate(settings);
    g_buffer.checkStatus();

1パス目でジオメトリを普通にMRT

 1パス目のポリゴンのGBufferへのレンダリング。ここでも、特別なことは何にもしていない。
[source]
(https://github.com/yumataesu/ModernOpenGL-AdventCal2017/blob/7ece3a72d6d2e501221ae0417b851578946eedd0/21-render_raymarching_and_geometry_at_the_same_time/src/ofApp.cpp#L75-L94)

2パス目でRaymarchingのシーンを書き込む

 ここで重要なのは2つ

  • 1パス目と同じカメラ情報で、rayを定義すること
  • rayの衝突判定からシーンの深度を構築し、その値でgl_FragDepthを更新すること

 深度を更新しないと、適切な前後関係で、シーンがレンダーされない
しかし、RayMarchingは、ただの板ポリにfragment shaderで描画しているだけなので、深度値はつねに1である。
そのため自前で、Rayの衝突位置から深度値を計算する必要がある。
source

この深度値で、gl_FragDepthを更新する。

 2パス目ではglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);をせず、GBufferにレンダーする。
source

これで、RayMarchingとofBoxPrimitiveが共存するGBufferができる。

8月-24-2017 14-40-35.gif
GBufferの中身。正しい前後関係でレンダリングされていることが確認できる。

後はライティングを行う

 ここまでくると、後は一般的な遅延シェーディング処理を行うだけ。
8月-24-2017 13-50-24.gif

最終レンダリング結果 | 緑のSphereは、Raymarching。赤のCubeは、ofBoxPrimitive。
ライティングが一貫しているのが確認できる。

まとめ

 このテクニックを利用すれば、キャラクターアニメーションの後ろで、
フラクタルやトンネルがバキバキ動いているという複雑なシーンをレンダーすることができる。
 GBufferが生成できたので、スクリーンスペース系のテクニック(SSAOとか, SSRとか)も今まで通り使えるはず。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?