--- id: wiki-2026-0508-렌더링-파이프라인-rendering-pipeline title: 렌더링 파이프라인(Rendering Pipeline) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Rendering Pipeline, Graphics Pipeline, GPU Pipeline] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [graphics, gpu, rendering, real-time] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: glsl/wgsl framework: Vulkan / DirectX 12 / WebGPU --- # 렌더링 파이프라인(Rendering Pipeline) ## 매 한 줄 > **"매 vertex → fragment → screen pixel로 변환하는 GPU의 stage chain"**. 1990s fixed-function OpenGL에서 시작 → programmable shaders (GeForce 3, 2001) → modern compute-driven pipeline (mesh shaders, DX12 Ultimate)으로 evolve. 2026 현재 Vulkan 1.4 · DirectX 12 Ultimate · WebGPU가 cross-platform standard, ray-traced GI + neural rendering (DLSS 4, FSR 4)이 default. ## 매 핵심 ### 매 Classic Pipeline (Stages) - **Input Assembly (IA)**: 매 vertex buffer + index buffer → primitive. - **Vertex Shader (VS)**: 매 per-vertex transform (world → view → clip). - **Tessellation / Geometry**: 매 optional — adaptive subdivision, particle expansion. - **Rasterization**: 매 primitive → fragments (interpolated). - **Fragment / Pixel Shader (FS)**: 매 per-pixel shading (PBR, lighting). - **Output Merger**: 매 depth/stencil test + blend → framebuffer. ### 매 Modern Compute-Driven - **Mesh Shaders** (DX12 Ultimate, Vulkan): 매 IA + VS + Geom 대체, GPU-driven culling. - **Ray Tracing**: 매 RT cores → BVH traversal → shadow / GI / reflection. - **Variable Rate Shading (VRS)**: 매 영역별 shading rate 조절. - **Neural Upscaling**: 매 DLSS 4 / FSR 4 / XeSS 2 — render at 1/4 res, upsample to 4K. ### 매 응용 1. Unreal Engine 5 Nanite — virtualized geometry, mesh-shader based. 2. Unity HDRP — render graph, customizable per-frame. 3. WebGPU (Chrome 120+) — browser-native compute + render. 4. Godot 4.4 — Vulkan-first, mobile-aware forward+ renderer. ## 💻 패턴 ### WebGPU Render Pipeline Setup ```javascript const pipeline = device.createRenderPipeline({ layout: 'auto', vertex: { module: device.createShaderModule({ code: vsWGSL }), entryPoint: 'main', buffers: [{ arrayStride: 32, attributes: [ { shaderLocation: 0, offset: 0, format: 'float32x3' }, // pos { shaderLocation: 1, offset: 12, format: 'float32x3' }, // normal { shaderLocation: 2, offset: 24, format: 'float32x2' }, // uv ], }], }, fragment: { module: device.createShaderModule({ code: fsWGSL }), entryPoint: 'main', targets: [{ format: 'bgra8unorm' }], }, primitive: { topology: 'triangle-list', cullMode: 'back' }, depthStencil: { format: 'depth24plus', depthWriteEnabled: true, depthCompare: 'less' }, }); ``` ### Forward+ Tiled Light Culling (WGSL compute) ```wgsl @group(0) @binding(0) var lights: array; @group(0) @binding(1) var tile_lights: array; @group(0) @binding(2) var depth_tex: texture_depth_2d; @compute @workgroup_size(16, 16) fn cs_main(@builtin(global_invocation_id) gid: vec3) { let tile = gid.xy / 16u; let frustum = build_tile_frustum(tile, depth_tex); var idx: u32 = 0u; for (var i = 0u; i < arrayLength(&lights); i = i + 1u) { if (sphere_in_frustum(lights[i].pos_radius, frustum)) { tile_lights[tile_offset(tile) + idx] = i; idx = idx + 1u; } } } ``` ### Vulkan Command Buffer ```cpp VkCommandBufferBeginInfo begin{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; vkBeginCommandBuffer(cmd, &begin); VkRenderingAttachmentInfo color{}; color.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; color.imageView = swapchainView; color.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; color.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; color.storeOp = VK_ATTACHMENT_STORE_OP_STORE; color.clearValue = {.color = {{0, 0, 0, 1}}}; VkRenderingInfo info{VK_STRUCTURE_TYPE_RENDERING_INFO}; info.renderArea = {{0, 0}, extent}; info.layerCount = 1; info.colorAttachmentCount = 1; info.pColorAttachments = &color; vkCmdBeginRendering(cmd, &info); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdDraw(cmd, 3, 1, 0, 0); vkCmdEndRendering(cmd); vkEndCommandBuffer(cmd); ``` ### PBR Fragment Shader (WGSL) ```wgsl fn fresnel_schlick(cos_theta: f32, F0: vec3) -> vec3 { return F0 + (vec3(1.0) - F0) * pow(1.0 - cos_theta, 5.0); } fn distribution_ggx(N: vec3, H: vec3, roughness: f32) -> f32 { let a = roughness * roughness; let a2 = a * a; let NdotH = max(dot(N, H), 0.0); let denom = (NdotH * NdotH * (a2 - 1.0) + 1.0); return a2 / (3.14159 * denom * denom); } @fragment fn fs_main(in: VsOut) -> @location(0) vec4 { let N = normalize(in.normal); let V = normalize(camera_pos - in.world_pos); let L = normalize(light_pos - in.world_pos); let H = normalize(V + L); let F0 = mix(vec3(0.04), albedo, metallic); let F = fresnel_schlick(max(dot(H, V), 0.0), F0); let D = distribution_ggx(N, H, roughness); let G = geometry_smith(N, V, L, roughness); let specular = (D * G * F) / (4.0 * max(dot(N, V), 0.001) * max(dot(N, L), 0.001)); let kD = (vec3(1.0) - F) * (1.0 - metallic); let diffuse = kD * albedo / 3.14159; let radiance = light_color * max(dot(N, L), 0.0); return vec4((diffuse + specular) * radiance, 1.0); } ``` ### Render Graph (UE5-style) ```cpp auto& depth = graph.create_texture("Depth", {1920, 1080, VK_FORMAT_D32_SFLOAT}); auto& gbuffer = graph.create_texture("GBuffer", {1920, 1080, VK_FORMAT_R16G16B16A16_SFLOAT}); graph.add_pass("GBuffer", [&](PassBuilder& b) { b.write(gbuffer); b.write(depth); return [=](CommandBuffer& cmd) { draw_opaque(cmd); }; }); graph.add_pass("Lighting", [&](PassBuilder& b) { b.read(gbuffer); b.read(depth); b.write(swapchain); return [=](CommandBuffer& cmd) { fullscreen_pass(cmd, lighting_pso); }; }); graph.compile_and_execute(cmd); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Cross-platform (incl. web) | WebGPU | | AAA PC / console | Vulkan / DX12 with mesh shaders | | Mobile-first | OpenGL ES 3.2 / Vulkan Mobile | | Real-time RT | DXR 1.1 / Vulkan KHR_ray_tracing | | Indie / prototype | Unity URP / Godot Forward+ | **기본값**: Vulkan 1.3+ render-graph + forward+ tile-based + DLSS/FSR upscale. ## 🔗 Graph - 부모: [[Computer_Graphics]] · [[GPU_Architecture]] - 변형: [[Deferred_Rendering]] - 응용: [[WebGPU]] ## 🤖 LLM 활용 **언제**: shader template generation, render-graph pass scaffolding, debug-message interpretation. **언제 X**: 매 perf-critical inner loop optimization — RenderDoc / NSight profiler가 ground truth. ## ❌ 안티패턴 - **Immediate-mode draw calls**: 매 draw call 수천 → CPU bottleneck (use indirect draws). - **Stalls on map/unmap**: 매 GPU upload 동기화 → frame hitch (use staging + double buffer). - **No depth pre-pass**: 매 expensive overdraw on dense scenes. - **Heavy fragment for far objects**: 매 mip / LOD 무시. ## 🧪 검증 / 중복 - Verified (Vulkan 1.4 spec, "Real-Time Rendering 4th ed", DigitalFoundry 2025 analyses). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — graphics pipeline stages + modern compute-driven + WebGPU/Vulkan code 정리 |