Offscreen Rendering(오프스크린 렌더링)은 3D 장면을 화면이 아닌 텍스처 버퍼(FBO — Framebuffer Object)에 렌더링한 후 텍스처로 사용할 수 있는 기술입니다. Apple Metal Documentation, 2025에 따르면, 오프스크린 렌더링은 그림자, 반사, 후처리 효과 및 그래픽 전처리를 만드는 데 사용됩니다. Offscreen Rendering을 사용하면 복잡한 장면을 품질 손실 없이 패스(pass)로 분할할 수 있습니다.
핵심 포인트
Offscreen Rendering은 그래픽 콘텐츠를 화면에 표시되는 메인 프레임버퍼 대신 비디오 메모리의 중간 버퍼에 렌더링하는 방법입니다. 오프스크린 렌더링의 결과는 텍스처 또는 renderbuffer에 저장됩니다.
오프스크린 렌더링의 주요 목적은 멀티패스 렌더링(multi-pass rendering)입니다. 복잡한 장면은 여러 패스로 분할됩니다. 먼저 장면이 텍스처(offscreen)에 렌더링된 다음 이 텍스처가 다음 패스의 입력으로 사용되며 최종 이미지를 얻을 때까지 계속됩니다. 이 접근 방식을 통해 단일 패스로는 불가능한 효과를 얻을 수 있습니다.
OpenGL ES에서 오프스크린 렌더링의 주요 메커니즘은 Framebuffer Object(FBO)입니다. FBO는 텍스처 이미지나 renderbuffer 객체를 연결할 수 있는 컨테이너입니다. FBO를 바인딩하면 이후의 모든 렌더링 명령이 화면 대신 연결된 텍스처로 전송됩니다.
Offscreen Rendering은 별도의 프레임버퍼 객체를 생성하고 여기에 텍스처 또는 renderbuffer를 연결한 후 렌더링 컨텍스트를 이 FBO로 전환하고 드로우 명령을 실행하여 구현됩니다. 패스가 완료되면 컨텍스트가 메인 프레임버퍼로 돌아갑니다.
프로세스는 세 단계로 구성됩니다. 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 | 뎁스 버퍼 사전 채우기 |
렌더링 결과를 나중에 사용하기 위해 텍스처에 저장하는 기본 기술입니다. Render-to-Texture는 미니맵, 동적 객체의 텍스처 및 복잡한 재료의 사전 시각화에 사용됩니다.
복잡한 효과(HDR, bloom, depth of field)는 여러 순차적 패스가 필요합니다. 각 패스는 장면을 오프스크린 텍스처에 렌더링하고, 필터를 적용하며, 결과를 다음 패스로 전달합니다. 이 접근 방식을 통해 최종 이미지 품질 손실 없이 효과를 축적할 수 있습니다.
Shadow Mapping은 오프스크린 렌더링의 전형적인 예입니다. 그림자는 두 패스로 생성됩니다. 먼저 장면이 광원의 관점에서 뎁스 텍스처(offscreen)로 렌더링된 다음 메인 렌더링 중에 각 프래그먼트가 이 뎁스 맵과 비교되어 그림자에 있는지 확인합니다.
첫 번째 패스: 카메라가 광원 위치에 배치되고 장면이 오프스크린 버퍼로 렌더링되어 텍스처에 깊이만 기록됩니다. 두 번째 패스: 각 프래그먼트를 확인하는 메인 렌더링 — 프래그먼트의 깊이가 뎁스 맵의 값보다 크면 해당 프래그먼트는 음영 처리됩니다.
// 섀도우 매핑용 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 전환에는 파이프라인 플러시와 추가 시간이 필요합니다.
모바일 장치의 경우 권장 사항: 결과를 읽을 필요가 없으면 텍스처 대신 renderbuffer 사용(깊이 전용 패스); 오프스크린 텍스처의 최소 필요 해상도 선택; 가능한 경우 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은 그래픽이 화면이 아닌 보이지 않는 버퍼(텍스처)에 그려지는 것입니다. 이 버퍼는 다른 효과를 위한 텍스처로 사용됩니다. 마치 투명 시트에 그림을 그린 다음 최종 이미지 위에 겹치는 것과 같습니다.
오프스크린 렌더링을 사용하면 단일 패스로 불가능한 효과를 만들 수 있습니다: 그림자(광원의 관점에서 렌더링), 반사, 블러, 블룸(bloom) 및 HDR 토닝. 각 효과에는 오프스크린 텍스처로의 별도 패스가 필요합니다.
네, 각 오프스크린 패스는 장면이 다시 렌더링되므로 GPU 작업량이 두 배가 됩니다. 최적화에는 오프스크린 텍스처 해상도 감소, renderbuffer 사용, MRT(Multiple Render Targets)를 통한 패스 병합이 포함됩니다.
FBO(Framebuffer Object)는 텍스처 또는 renderbuffer가 연결되는 컨테이너입니다. 텍스처는 렌더링 결과를 읽을 수 있습니다(섀도우 매핑, 후처리 효과에 필요). Renderbuffer는 더 빠르지만 그 내용을 텍스처로 사용할 수 없습니다.
모든 최신 그래픽 API: OpenGL ES(FBO를 통해), Apple Metal(MTLRenderPassDescriptor를 통해), Vulkan(VkFramebuffer를 통해), Direct3D(Render Target View를 통해). 개념적으로 메커니즘은 동일합니다 — 화면 대신 텍스처로 렌더링합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.