Offscreen Rendering (позаекранний рендеринг) — це техніка рендерингу 3D-сцени не на екран, а в текстурний буфер (FBO — Framebuffer Object), який потім може бути використаний як текстура. За даними Apple Metal Documentation, 2025, позаекранний рендеринг застосовується для створення тіней, відображень, пост-ефектів та попередньої обробки графіки. Offscreen Rendering дозволяє розділити складну сцену на проходи (passes) без втрати якості.
Головне
Offscreen Rendering — це метод рендерингу графічного вмісту в проміжний буфер у відеопам'яті, а не в основний кадровий буфер (framebuffer), який виводиться на екран. Результат позаекранного рендерингу зберігається в текстуру або renderbuffer.
Основна мета позаекранного рендерингу — багатопрохідний рендеринг (multi-pass rendering). Складна сцена розбивається на кілька проходів: спочатку сцена рендериться в текстуру (offscreen), потім ця текстура використовується як вхідні дані для наступного проходу, і так до отримання фінального зображення. Такий підхід дозволяє реалізувати ефекти, неможливі за один прохід.
Ключовий механізм позаекранного рендерингу в OpenGL ES — Framebuffer Object (FBO). FBO — це контейнер, до якого можна прикріпити текстурні зображення або renderbuffer-об'єкти. Після прив'язки FBO всі наступні команди рендерингу направляються в прикріплену текстуру, а не на екран.
Offscreen Rendering реалізується через створення окремого framebuffer-об'єкта, прикріплення до нього текстури або renderbuffer, перемикання контексту рендерингу на цей FBO та виконання команд відмальовки. Після завершення проходу контекст перемикається назад на основний framebuffer.
Процес складається з трьох кроків: створення 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 використовується для широкого спектру графічних ефектів. Кожна техніка потребує одного або кількох позаекранних проходів та певної конфігурації FBO.
| Техніка | Кількість проходів | Призначення |
|---|---|---|
| Shadow Mapping | 2+ | Генерація карти тіней із джерела світла |
| Reflection Mapping | 1-2 | Рендеринг відображень у кубічну карту |
| Bloom Effect | 3-5 | Сяйво яскравих ділянок зображення |
| HDR Rendering | 2 | Тон-мапінг для HDR-зображень |
| Depth Prepass | 1 | Попереднє заповнення depth buffer |
Базова техніка, при якій результат рендерингу зберігається в текстуру для подальшого використання. Render-to-Texture застосовується для створення міні-карт, текстур динамічних об'єктів та попередньої візуалізації складних матеріалів.
Складні ефекти (HDR, bloom, depth of field) потребують кількох послідовних проходів. Кожен прохід рендерить сцену в позаекранну текстуру, застосовує фільтр і передає результат наступному проходу. Такий підхід дозволяє накопичувати ефекти без втрати якості фінального зображення.
Shadow Mapping — класичний приклад використання позаекранного рендерингу. Тінь створюється в два проходи: спочатку сцена рендериться з точки зору джерела світла в depth-текстуру (offscreen), потім при основному рендерингу кожен фрагмент порівнюється з цією depth-картою для визначення, чи знаходиться він у тіні.
Перший прохід: камера встановлюється в позицію джерела світла, сцена рендериться в позаекранний буфер, записуючи лише глибину (depth) у текстуру. Другий прохід: основний рендеринг з перевіркою кожного фрагмента — якщо його глибина більша, ніж значення в depth-карті, фрагмент затіняється.
// 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 потребує скидання конвеєра (pipeline flush) та додаткового часу.
Для мобільних пристроїв рекомендується: використовувати renderbuffer замість текстури, якщо не потрібно читання результату (depth-only pass); вибирати мінімально необхідну роздільну здатність позаекранних текстур; об'єднувати проходи, де це можливо, через 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);
// Перемикання назад на стандартний framebuffer
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 — це коли графіка малюється не на екран, а в невидимий буфер (текстуру). Цей буфер потім використовується як текстура для інших ефектів. Уявіть, що ви малюєте на прозорій плівці, яку потім накладаєте на фінальне зображення.
Позаекранний рендеринг дозволяє створювати ефекти, неможливі за один прохід: тіні (рендеринг з точки зору світла), відображення, розмиття, сяйво (bloom) та HDR-тонування. Кожен ефект потребує окремого проходу в позаекранну текстуру.
Так, кожен позаекранний прохід подвоює кількість роботи GPU, оскільки сцена рендериться повторно. Оптимізація включає зниження роздільної здатності позаекранних текстур, використання renderbuffer та об'єднання проходів через MRT (Multiple Render Targets).
FBO (Framebuffer Object) — це контейнер, до якого прикріплюються текстури або renderbuffer. Texture дозволяє читати результати рендерингу (потрібно для shadow mapping, пост-ефектів). Renderbuffer швидший, але його вміст не можна використовувати як текстуру.
Всі сучасні графічні API: OpenGL ES (через FBO), Apple Metal (через MTLRenderPassDescriptor), Vulkan (через VkFramebuffer), Direct3D (через Render Target View). Концептуально механізм однаковий — рендеринг у текстуру замість екрана.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також