Offscreen Rendering(オフスクリーンレンダリング)とは、3Dシーンを画面ではなくテクスチャバッファ(FBO — Framebuffer Object)にレンダリングする技術で、後でテクスチャとして使用できます。Apple Metal Documentation, 2025によると、オフスクリーンレンダリングはシャドウ、リフレクション、ポストエフェクト、グラフィックスの前処理に使用されています。Offscreen Renderingにより、複雑なシーンを品質を損なうことなくパスに分割できます。
重要なポイント
Offscreen Renderingとは、グラフィカルコンテンツを画面に表示されるメインフレームバッファではなく、ビデオメモリ内の中間バッファにレンダリングする方法です。オフスクリーンレンダリングの結果はテクスチャまたはレンダーバッファに保存されます。
オフスクリーンレンダリングの主な目的はマルチパスレンダリング(multi-pass rendering)です。複雑なシーンは複数のパスに分割されます。最初にシーンがテクスチャ(オフスクリーン)にレンダリングされ、次にこのテクスチャが次のパスの入力として使用され、最終画像が得られるまで続きます。このアプローチにより、単一のパスでは不可能なエフェクトを実現できます。
OpenGL ESにおけるオフスクリーンレンダリングの主要メカニズムはFramebuffer Object(FBO)です。FBOはテクスチャイメージやレンダーバッファオブジェクトをアタッチできるコンテナです。FBOをバインドすると、以降のすべてのレンダリングコマンドは画面ではなくアタッチされたテクスチャに送られます。
Offscreen Renderingは、別のフレームバッファオブジェクトを作成し、それにテクスチャまたはレンダーバッファをアタッチし、レンダリングコンテキストをこのFBOに切り替えて描画コマンドを実行することで実装されます。パスが完了すると、コンテキストはメインフレームバッファに戻ります。
プロセスは3つのステップで構成されます。FBOを作成してテクスチャをアタッチ — シーンをオフスクリーンテクスチャにレンダリング — 結果のテクスチャを次のパスで使用。GL_COLOR_ATTACHMENT0はレンダリング先のカラーテクスチャを決定します。
// オフスクリーンレンダリング用のFBO作成(OpenGL ES 3.0)
GLuint fbo, offscreenTex;
glGenFramebuffers(1, &fbo);
glGenTextures(1, &offscreenTex);
glBindTexture(GL_TEXTURE_2D, offscreenTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER),
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
offscreenTex, 0);
Offscreen Renderingは幅広いグラフィックエフェクトに使用されます。各技術は1つ以上のオフスクリーンパスと特定のFBO設定を必要とします。
| 技術 | パス数 | 目的 |
|---|---|---|
| Shadow Mapping | 2+ | 光源からのシャドウマップ生成 |
| Reflection Mapping | 1-2 | キューブマップへのリフレクションレンダリング |
| Bloom Effect | 3-5 | 画像の明るい部分の発光効果 |
| HDR Rendering | 2 | HDR画像のトーンマッピング |
| Depth Prepass | 1 | デプスバッファの事前設定 |
レンダリング結果を後で使用するためにテクスチャに保存する基本的な技術です。Render-to-Textureはミニマップ、動的オブジェクトのテクスチャ、複雑なマテリアルの事前可視化に使用されます。
複雑なエフェクト(HDR、bloom、depth of field)には複数の連続パスが必要です。各パスはシーンをオフスクリーンテクスチャにレンダリングし、フィルターを適用して結果を次のパスに渡します。このアプローチにより、最終画像の品質を損なうことなくエフェクトを蓄積できます。
Shadow Mappingはオフスクリーンレンダリングの古典的な例です。シャドウは2つのパスで作成されます。最初にシーンが光源の視点からデプステクスチャ(オフスクリーン)にレンダリングされ、次にメインレンダリング時に各フラグメントがこのデプスマップと比較されて影の中にあるかどうかが判断されます。
第1パス:カメラを光源の位置に配置し、シーンをオフスクリーンバッファにレンダリングし、テクスチャに深度のみを記録します。第2パス:各フラグメントをチェックするメインレンダリング — その深度がデプスマップの値より大きい場合、フラグメントは影付きになります。
// シャドウマッピング用のFragment Shader
in vec4 vShadowCoord;
uniform sampler2D uShadowMap;
float calcShadow(vec4 coord) {
vec3 uvw = coord.xyz / coord.w;
float depth = texture(uShadowMap, uvw.xy).r;
return (uvw.z > depth + 0.005) ? 0.3 : 1.0;
}
Offscreen Renderingは追加のGPUパスを追加し、全体的な計算負荷と消費電力を増加させます。モバイル開発ではこれが特に重要です。FBOを切り替えるたびにパイプラインフラッシュと追加の時間が必要になります。
モバイルデバイス向けの推奨事項:結果を読み取る必要がない場合はテクスチャの代わりにレンダーバッファを使用(深度のみのパス);オフスクリーンテクスチャには必要最小限の解像度を選択;可能な場合はMRT(Multiple Render Targets)を使用してパスを統合。
Offscreen Renderingは各プラットフォームの独自APIを通じて実装されます。OpenGL ESとApple Metalの例を見てみましょう。
// FBOセットアップとシーンのテクスチャへのレンダリング
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, texWidth, texHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(offscreenProgram);
glBindVertexArray(sceneVAO);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0);
// デフォルトのフレームバッファに戻す
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Metal:テクスチャへのオフスクリーンレンダーパス
MTLRenderPassDescriptor passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
passDesc.colorAttachments[0].texture = offscreenTexture;
passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
passDesc.colorAttachments[0].clearColor =
MTLClearColorMake(0.0, 0.0, 0.0, 0.0);
id<MTLCommandBuffer> cmdBuffer = [commandQueue commandBuffer];
id<MTLRenderCommandEncoder> enc =
[cmdBuffer renderCommandEncoderWithDescriptor:passDesc];
[enc drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:indexCount
indexType:MTLIndexTypeUInt16
indexBuffer:indexBuffer
indexBufferOffset:0];
[enc endEncoding];
よくある質問
Offscreen Renderingとは、グラフィックスを画面ではなく目に見えないバッファ(テクスチャ)に描画することです。このバッファは後で他のエフェクトのテクスチャとして使用されます。まるで透明なシートに絵を描いて、それを最終画像に重ねるようなものです。
オフスクリーンレンダリングにより、1回のパスでは不可能なエフェクトを作成できます:シャドウ(光源の視点からのレンダリング)、リフレクション、ブラー、ブルーム(bloom)、HDRトーニング。各エフェクトにはオフスクリーンテクスチャへの個別のパスが必要です。
はい、各オフスクリーンパスはシーンが再レンダリングされるためGPUの作業量が2倍になります。最適化には、オフスクリーンテクスチャの解像度を下げること、レンダーバッファの使用、MRT(Multiple Render Targets)によるパスの統合が含まれます。
FBO(Framebuffer Object)はテクスチャやレンダーバッファをアタッチするコンテナです。テクスチャはレンダリング結果の読み取りを許可します(シャドウマッピング、ポストエフェクトに必要)。レンダーバッファは高速ですが、その内容をテクスチャとして使用することはできません。
最新のグラフィックスAPIすべてがサポートしています:OpenGL ES(FBO経由)、Apple Metal(MTLRenderPassDescriptor経由)、Vulkan(VkFramebuffer経由)、Direct3D(Render Target View経由)。概念的にはメカニズムは同じで、画面の代わりにテクスチャにレンダリングします。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。