Skip to content

Latest commit

ย 

History

78 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

JYEngine

image
Windows 10+  ยท  Direct3D 12 (FL 11.0+)  ยท  C++17  ยท  Visual Studio + Win10 SDK

GitHub: https://github.com/KULEEEE/JYEngine

ํ•œ๊ตญ์–ด | English


์š”์•ฝ

Data-Oriented Design์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„ํ•œ DirectX 12 ์ปค์Šคํ…€ ๋ Œ๋”๋ง ์—”์ง„์ด๋‹ค. Scene/Component ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋ง ์ „์šฉ Frame Snapshot๊ณผ Draw Item Cache๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , Renderer๋Š” ์›๋ณธ Scene์ด ์•„๋‹Œ ์บ์‹œ๋œ ๋ถˆ๋ณ€(immutable) ํ”„๋ ˆ์ž„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Forward / Deferred path๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. Transform์€ SoA ๊ตฌ์กฐ์™€ dirty index๋กœ ๊ฐฑ์‹  ๋น„์šฉ์„ ์ค„์˜€์œผ๋ฉฐ, RenderObject ๋ณ€๊ฒฝ์€ Draw Item Cache์— ๋ฐ˜์˜ํ•œ๋‹ค.

์นด๋ฉ”๋ผ๋ณ„ Frustum Culling์œผ๋กœ visible draw item์„ ๊ตฌ์„ฑํ•˜๊ณ , Deferred path๋Š” Shadow, Depth Pre-Pass, G-Buffer, SSAO, Lighting, Forward Overlay Pass๋กœ ๋ถ„๋ฆฌํ•œ๋‹ค. DirectX 12 ๋ฆฌ์†Œ์Šค, descriptor, command queue, render target, root signature๋Š” ์ž์ฒด ๋ Œ๋”๋ง API๋กœ ๋ž˜ํ•‘ํ–ˆ์œผ๋ฉฐ, shader reflection๊ณผ RenderDB๋ฅผ ํ†ตํ•ด material, mesh, transform, light ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

์ „์ฒด ๋ฐ์ดํ„ฐ ํ๋ฆ„

โ–ฃ Authoring ยท mutable
   JScene
    ยท Entity / Component pools
    ยท dirty transform / camera / light
        โ”‚  events
        โ–ผ
โ–ฃ Render Frontend ยท CPU
   JRenderServer::SyncScene
    (consume events ยท update draw item cache ยท build snapshot)
        โ”‚
        โ”œโ”€โ”€โ–ถ JRenderSnapshotBuilder (์นด๋ฉ”๋ผ viewยทprojection, dirty transform โ†’ world, light snapshot)
        โ””โ”€โ”€โ–ถ JCameraRenderQueueBuilder (frustum 6-plane cull, visible opaque / transparent ์ธ๋ฑ์Šค)
        โ”‚
        โ–ผ
   โ”€โ”€ JFrameDesc (immutable) โ”€โ”€
        โ”‚
        โ–ผ
โ–ฃ Render Backend ยท GPU
   JRenderDB                       material / mesh / camera / transform / light GPU mirror
        โ”‚
        โ–ผ
   JRenderer::Render(JFrameDesc)
    ยท Forward  : SceneColorPass
    ยท Deferred : Shadow โ†’ Depth โ†’ GBuffer โ†’ SSAO โ†’ Lighting โ†’ ForwardOverlay

๋ Œ๋”๋ง ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ JScene โ†’ Snapshot โ†’ RenderDB โ†’ Renderer ์˜ ๋‹จ์ผ ๋ฐฉํ–ฅ ๊ตฌ์กฐ๋กœ ์„ค๊ณ„ํ–ˆ๋‹ค. Scene์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์›๋ณธ ์ƒํƒœ๋งŒ ๊ด€๋ฆฌํ•˜๊ณ , Renderer๋Š” ํ”„๋ ˆ์ž„๋งˆ๋‹ค ํ™•์ •๋œ JFrameDesc ์™€ RenderDB ๋งŒ ์ฐธ์กฐํ•˜๋„๋ก ๋ถ„๋ฆฌํ–ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋ถ„๋ฆฌํ•˜๋ฉด Scene ๋ณ€๊ฒฝ ์ถ”์ ์ด ๋‹จ์ˆœํ•ด์ง€๊ณ , ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋งŒ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ RenderPass๊ฐ€ ๊ฐ€๋ณ€ํ•˜๋Š” Scene์— ์ง์ ‘ ์˜์กดํ•˜์ง€ ์•Š์•„ ๋””๋ฒ„๊น… ๊ฒฝ๊ณ„๊ฐ€ ๋ช…ํ™•ํ•˜๊ณ , Sorting Queue ์ƒ์„ฑ์ด๋‚˜ Snapshot ๋นŒ๋“œ ๊ฐ™์€ ๋‹จ๊ณ„์˜ ๋ณ‘๋ ฌํ™”์™€ ์ตœ์ ํ™”๊ฐ€ ์‰ฌ์›Œ์ ธ ์ถ”ํ›„ ์ ์šฉํ•  Multi Thread Rendering ๊ตฌ์กฐ์— ์ ํ•ฉํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜์˜€๋‹ค.

Data-Oriented Design

Data-Oriented Design์˜ ํ•ต์‹ฌ์€ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ํŒจํ„ด์„ ๊ธฐ์ค€์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ฐฐ์น˜๋ฅผ ์„ค๊ณ„ํ•ด Cache Hit๋ฅผ ๋†’์ด๊ณ , ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ด๋‹ค. ๊ฐ์ฒด ๋‹จ์œ„์˜ ์ถ”์ƒํ™”๋ณด๋‹ค ๋งค ํ”„๋ ˆ์ž„ ๋ฐ˜๋ณต๋˜๋Š” ์ฒ˜๋ฆฌ ํ๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ–ˆ์œผ๋ฉฐ, ๊ฐ™์€ ๊ณ„์‚ฐ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ์—ฐ์†๋œ ๊ตฌ์กฐ๋กœ ๋ฌถ์–ด ์ˆœ์ฐจ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

๋˜ํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋งค ํ”„๋ ˆ์ž„ ๋‹ค์‹œ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ , ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ์™€ ๋ Œ๋”๋ง์— ์‹ค์ œ๋กœ ํ•„์š”ํ•œ Hot Data๋งŒ ์„ ๋ณ„ํ•ด Snapshot๊ณผ Draw Item Cache๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Scene์˜ ๋ฐ์ดํ„ฐ์™€ Renderer์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ , ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ์—์„œ๋Š” Cache ์นœํ™”์ ์ธ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ํ–ˆ๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ JTransformPool ์€ translation / rotation / scale์„ ๊ฐ๊ฐ ๋ณ„๋„์˜ std::vector ๋กœ ๋ณด๊ด€ํ•˜๋Š” SoA(Structure of Arrays) ๊ตฌ์กฐ์ด๋ฉฐ, ๋ณ€๊ฒฝ๋œ ์ธ๋ฑ์Šค๋งŒ dirty ring์— ๋ˆ„์ ํ•ด ๊ทธ ํ”„๋ ˆ์ž„์— ๋ฐ”๋€ transform๋งŒ world matrix๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

// JTransformPool โ€” SoA + dirty index ring
std::vector<JVec3>  _translations;
std::vector<JVec3>  _rotations;
std::vector<JVec3>  _scales;
std::vector<uint8>  _dirtyFlags;    // ์ค‘๋ณต push ๋ฐฉ์ง€
std::vector<uint32> _dirtyIndices;  // ์ด ํ”„๋ ˆ์ž„์— ๋ณ€๊ฒฝ๋œ ์ธ๋ฑ์Šค๋งŒ ๋ˆ„์ 

Component Pool

Scene์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์ฒด ๋‹จ์œ„๋กœ ํฉ์–ด ๋‘์ง€ ์•Š๊ณ  ๊ฐ™์€ ์ข…๋ฅ˜๋ผ๋ฆฌ Pool์— ๋ชจ์•„ ์ง์ ‘ ์†Œ์œ ํ•œ๋‹ค. ํ•ต์‹ฌ์€ ์™ธ๋ถ€(Sceneยท์‹œ์Šคํ…œ)๊ฐ€ ์ปดํฌ๋„ŒํŠธ์˜ ์ฃผ์†Œ๋ฅผ ๋“ค์ง€ ์•Š๊ณ  ๊ฐ€๋ฒผ์šด ํ•ธ๋“ค๋กœ๋งŒ ๊ฐ€๋ฆฌํ‚ค๋ฉฐ, ์‹ค์ œ ์ ‘๊ทผ์€ ๋งค๋ฒˆ ํ’€์„ ๊ฑฐ์นœ๋‹ค๋Š” ์ ์ด๋‹ค.

struct JEntityHandle { uint32 index; uint32 generation; };

template <typename TData>
struct JPoolSlot { uint32 generation; bool active; TData data; };

template <typename TData>
class JEntityPool {
    std::vector<JPoolSlot<TData>> _slots;
    std::vector<uint32>           _freeIndices;
};

์ด๋ ‡๊ฒŒ ํฌ์ธํ„ฐ ๋Œ€์‹  ํ•ธ๋“ค์„ ์“ฐ๋Š” ๊ฒƒ์ด Pool ๊ตฌ์กฐ์˜ ๊ถ๊ทน์ ์ธ ์ด์œ ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌ์ธํ„ฐ๋กœ ์ง์ ‘ ๋“ค๊ณ  ์žˆ์—ˆ๋‹ค๋ฉด, ํ’€์ด ๋‚ด๋ถ€ ๋ฐฐ์—ด์„ ํ‚ค์šฐ๊ฑฐ๋‚˜(std::vector ์žฌํ• ๋‹น) ์Šฌ๋กฏ์„ ์žฌ๋ฐฐ์น˜ํ•˜๋Š” ์ˆœ๊ฐ„ ๊ทธ ์ฃผ์†Œ๋“ค์ด ์ „๋ถ€ ๋ฌดํšจ๊ฐ€ ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ๋ฐฐ์น˜๋ฅผ ์‚ฌ์‹ค์ƒ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋‹ค. ํ•ธ๋“ค์€ ์ ‘๊ทผ ์‹œ์ ์— ํ’€์—์„œ ์œ„์น˜๋ฅผ ๋‹ค์‹œ ์ฐพ์œผ๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋””๋กœ ์˜ฎ๊ฒจ๊ฐ€๋„ ์™ธ๋ถ€ ์ฐธ์กฐ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰ ์•„๋ฌด๋„ ์ฃผ์†Œ๋ฅผ ๋“ค๊ณ  ์žˆ์ง€ ์•Š๊ธฐ์— ํ’€์ด ๋ฐ์ดํ„ฐ ๋ฐฐ์น˜๋ฅผ ์ž์œ ๋กญ๊ฒŒ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ™์€ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ์†ยทSoA๋กœ ๋ชจ์•„ Cache Hit์œจ์„ ๋†’์ด๋Š” ์ตœ์ ํ™”(์•ž์„œ ๋ณธ JTransformPool์˜ SoA ๋ถ„๋ฆฌ)๊ฐ€ ๋ฐ”๋กœ ์ด ์œ„์—์„œ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค. ํ•ธ๋“ค์— ํ•จ๊ป˜ ๋‹ด๊ธด generation์€ ์‚ญ์ œ ํ›„ ์žฌ์‚ฌ์šฉ๋œ ์Šฌ๋กฏ์„ ๊ตฌ๋ถ„ํ•ด, ์‚ฌ๋ผ์ง„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์˜› ํ•ธ๋“ค์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ฑธ๋Ÿฌ ์ฃผ๋Š” ์•ˆ์ „์žฅ์น˜ ์—ญํ• ์„ ํ•œ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ฐ์ฒด ๊ฐ„ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋Š” ๋ถˆ๊ทœ์น™ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์ด ์‚ฌ๋ผ์ง€๊ณ , Transform ๊ฐฑ์‹ ์ด๋‚˜ RenderObject ์ˆœํšŒ์ฒ˜๋Ÿผ ๋งค ํ”„๋ ˆ์ž„ ๋ฐ˜๋ณต๋˜๋Š” ์ž‘์—…์ด ์—ฐ์†๋œ ๋ฐฐ์—ด์„ ์ˆœ์ฐจ ์ ‘๊ทผํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ๋œ๋‹ค. ๊ฐ ์ปดํฌ๋„ŒํŠธ ํ’€์€ Entity index๋ฅผ ๊ทธ๋Œ€๋กœ ์ปดํฌ๋„ŒํŠธ ์Šฌ๋กฏ ์ธ๋ฑ์Šค๋กœ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ํ•œ ์—”ํ‹ฐํ‹ฐ๋‹น ๊ฐ™์€ ์ข…๋ฅ˜์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ํ•˜๋‚˜๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ  lookup์€ ํ•ด์‹œ ์—†์ด ์ธ๋ฑ์‹ฑ๋งŒ์œผ๋กœ ๋๋‚œ๋‹ค.

Entity Index      0        1        2        3        4
EntityPool      active   active    free    active   active
RenderObject    mesh/                       mesh/    mesh/
Pool            material                    material material
TransformPool    SoA      SoA               SoA      SoA

Snapshot

Snapshot์€ DOD ๊ด€์ ์—์„œ Scene ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋ง์ด ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ์žฌ๋ฐฐ์น˜ํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. Scene์€ Entity์™€ Component๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์ข‹์€ ๊ตฌ์กฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•˜์ง€๋งŒ, Renderer๋Š” ๋งค ํ”„๋ ˆ์ž„ ๊ณ„์‚ฐ๋œ world matrix, viewProjection, light parameter, visible draw item ๋ชฉ๋ก์ฒ˜๋Ÿผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋งŒ ํ•„์š”ํ•˜๋‹ค.

๋”ฐ๋ผ์„œ Snapshot ๋‹จ๊ณ„์—์„œ CPU-side Component ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , Renderer๊ฐ€ ์›๋ณธ Scene์„ ๋‹ค์‹œ ํƒ์ƒ‰ํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด์˜ ์†Œ์œ  ๊ด€๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ ์‹ค์ œ ์‚ฌ์šฉ ํ๋ฆ„ ๊ธฐ์ค€์œผ๋กœ ์žฌ๊ตฌ์„ฑํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์ ‘๊ทผ๊ณผ ๊ณ„์‚ฐ์„ ์ค„์ด๋Š” DOD ์„ค๊ณ„์ด๋‹ค.

RenderObject์˜ ๋ณ€๊ฒฝ์€ ๋งค ํ”„๋ ˆ์ž„ ์ „์ฒด๋ฅผ ์žฌ๊ตฌ์ถ•ํ•˜์ง€ ์•Š๊ณ  JDrawItemCache ์— ์ฆ๋ถ„ ๋ฐ˜์˜ํ•œ๋‹ค. Scene ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ Added ๋Š” draw item์„ append, Modified ๋Š” ๊ธฐ์กด range๋ฅผ in-place patch, Removed ์ผ ๋•Œ๋งŒ rebuild ํ•œ๋‹ค.

DirectX 12 APIํ™”

DirectX 12์˜ explicitํ•œ ์ œ์–ด๊ถŒ์€ ์œ ์ง€ํ•˜๋˜, ์ƒ์œ„ RenderPass๊ฐ€ Command Allocator, Descriptor Heap, Resource Upload, Root Binding์„ ์ง์ ‘ ์„ธ๋ถ€์ ์œผ๋กœ ๋‹ค๋ฃจ์ง€ ์•Š๋„๋ก ๋ Œ๋”๋ง Abstraction Layer๋ฅผ ๊ตฌ์„ฑํ–ˆ๋‹ค.

JRenderContext

JRenderContext๋Š” GPU ๋ฆฌ์†Œ์Šค ์ƒ์„ฑ์„ ๋‹ด๋‹นํ•œ๋‹ค. CreateVertexBuffer, CreateIndexBuffer, CreateConstantBuffer, CreateTextureFromFile, CreateShader, CreatePipeline, CreateRootSignature ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜์—ฌ DX12 Resource ์ƒ์„ฑ ๊ณผ์ •์„ ์—”์ง„ API ํ˜ธ์ถœ๋กœ ๋‹จ์ˆœํ™”ํ–ˆ๋‹ค.

JVertexBuffer* vb      = renderContext->CreateVertexBuffer(vertices, vertexCount);
JIndexBuffer*  ib      = renderContext->CreateIndexBuffer(indices);
JTexture*      texture = renderContext->CreateTextureFromFile(path);
JPipeline*     pipe    = renderContext->CreatePipeline(shader);

๋‚ด๋ถ€์—์„œ๋Š” Default Heap ์ƒ์„ฑ, Upload Buffer ๋ณต์‚ฌ, Resource Barrier ์ „ํ™˜, Descriptor ์ƒ์„ฑ ๊ฐ™์€ DX12 ์ ˆ์ฐจ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉํ•˜๋Š” ์ชฝ์—์„œ๋Š” GPU Resource๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋ณต์žกํ•œ ์ฝ”๋“œ๋ฅผ ๋งค๋ฒˆ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

JCommandQueue

JCommandQueue๋Š” ๋ Œ๋”๋ง ๋ช…๋ น ๊ธฐ๋ก์„ ๋‹จ์ˆœํ™”ํ•œ๋‹ค. RenderBegin, BeginRenderPass, BeginDepthPass, SetPipeline, SetGraphicResources, BindVertexBuffer, DrawIndexed, EndRenderPass, RenderEnd ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜์—ฌ RenderPass๊ฐ€ ํ•„์š”ํ•œ ๋ช…๋ น๋งŒ ์ˆœ์„œ๋Œ€๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

commandQueue->BeginRenderPass(renderTarget, clearColor, 1);
commandQueue->SetPipeline(materialResource->pipeline);
commandQueue->SetGraphicResources(&graphicResource);
commandQueue->BindVertexBuffer(meshResource);
commandQueue->DrawIndexed(indexCount, 1, startIndex, 0, 0);
commandQueue->EndRenderPass();

๋˜ํ•œ RenderTarget์˜ ์ƒํƒœ ์ „ํ™˜, Frame Resource๋ณ„ Upload Buffer(16 MB ์ƒ์ˆ˜ ๋ฒ„ํผ ์—…๋กœ๋“œ ๋ง), Descriptor Heap, Fence ๋™๊ธฐํ™”๋„ JCommandQueue ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌํ•œ๋‹ค. ๊ฐ™์€ ๋จธํ„ฐ๋ฆฌ์–ผ์ด ํ•œ ํ”„๋ ˆ์ž„ ์•ˆ์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ ๊ทธ๋ ค์งˆ ๋•Œ๋ฅผ ์œ„ํ•ด (shader, texture set) ํ‚ค๋กœ GPU descriptor table์„ ์บ์‹œํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด RenderPass๋Š” "์–ด๋–ค Target์— ์–ด๋–ค Resource๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ์–ด๋–ค Draw Call์„ ์‹คํ–‰ํ•  ๊ฒƒ์ธ๊ฐ€"์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

Shader Reflection ๊ธฐ๋ฐ˜ Binding

Shader Compile ์ดํ›„ D3DReflect ๋กœ cBuffer, Texture, Sampler Binding ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•œ๋‹ค. ์ด metadata๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Root Signature์™€ Graphic Resource Binding์„ ๊ตฌ์„ฑํ•˜์—ฌ, C++ ์ฝ”๋“œ๊ฐ€ shader register index๋ฅผ ์ง์ ‘ ๋ฐ˜๋ณต ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋„๋ก ํ–ˆ๋‹ค.

CompileShader()
 โ†’ D3DReflect(VS / PS)
 โ†’ collect BoundResources (CBUFFER / TEXTURE / SAMPLER)
 โ†’ build binding table
 โ†’ create root signature

cBuffer๋Š” root CBV๋กœ, Texture๋Š” descriptor table๋กœ ๋ฌถ์ด๊ณ , Sampler๋Š” static sampler๋กœ root signature์— ๋ฐ•ํžŒ๋‹ค. ๋”ฐ๋ผ์„œ ์Šฌ๋กฏ ์ธ๋ฑ์Šค๋ฅผ ์ฝ”๋“œ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ์…ฐ์ด๋”์™€ ๋™์ผํ•œ ์ด๋ฆ„๋งŒ ๋งž์ถ”๋ฉด ๋ฐ”์ธ๋”ฉ์ด ์—ฐ๊ฒฐ๋œ๋‹ค.

JGraphicResource::SetConstantBuffer("PerObject", buffer);
JGraphicResource::SetTexture("AlbedoMap", texture);

ํ•œ๋ฐœ ๋” ๋‚˜์•„๊ฐ€ ์ƒ˜ํ”Œ๋Ÿฌ์˜ ์ข…๋ฅ˜๊นŒ์ง€ ์ด๋ฆ„ ๊ทœ์•ฝ์œผ๋กœ ์ถ”๋ก ํ•œ๋‹ค โ€” ๋ฆฌ์†Œ์Šค ์ด๋ฆ„์— Shadow ๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ์—”์ง„์ด reverse-Z์šฉ ๋น„๊ต ์ƒ˜ํ”Œ๋Ÿฌ(GREATER_EQUAL + border)๋ฅผ ์ž๋™ ์ƒ์„ฑํ•œ๋‹ค. ์ƒˆ ์…ฐ์ด๋”๊ฐ€ ๊ทธ๋ฆผ์ž ๋น„๊ต ์ƒ˜ํ”Œ๋ง์„ ์“ฐ๋ ค๋ฉด ์ด๋ฆ„๋งŒ ๋งž์ถ”๋ฉด ๋œ๋‹ค.

Deferred Rendering Pipeline

Renderer๋Š” RenderPath::Forward / RenderPath::Deferred ๋ฅผ ๋Ÿฐํƒ€์ž„์— ์ „ํ™˜ํ•œ๋‹ค. Deferred path๋Š” ํ•˜๋‚˜์˜ ๊ฑฐ๋Œ€ํ•œ ์…ฐ์ด๋” ๋Œ€์‹ , ๊ฐ์ž ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์ด ๋ช…ํ™•ํ•œ 6๊ฐœ์˜ ๋…๋ฆฝ ํŒจ์Šค๋กœ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

JRenderer::Render(JFrameDesc)
   โ”‚
   โ”œโ”€โ–ถ JShadowPass          directional light ๊ธฐ์ค€ cascade depth ์ƒ์„ฑ (Texture2DArray)
   โ”œโ”€โ–ถ JDepthPass           ์นด๋ฉ”๋ผ ์‹œ์  reverse-Z depth pre-pass
   โ”œโ”€โ–ถ JGBufferPass         Albedo / Normal / Material(MRT 3์žฅ) ๊ธฐ๋ก
   โ”œโ”€โ–ถ JSSAOPass            depthยทnormal๋กœ ํ™”๋ฉด ๊ณต๊ฐ„ ์ฐจํ ๊ณ„์‚ฐ โ†’ AO ํƒ€๊ฒŸ (Lighting์ด ๋ธ”๋Ÿฌํ•ด ์‚ฌ์šฉ)
   โ”œโ”€โ–ถ JLightingPass        full-screen triangle๋กœ G-Buffer ์ƒ˜ํ”Œ๋ง โ†’ PBR ๋ผ์ดํŒ… + IBL
   โ””โ”€โ–ถ JForwardOverlayPass  ๋ฐ˜ํˆฌ๋ช…ยท๋””๋ฒ„๊ทธยท๊ทธ๋ฆฌ๋“œ ๋“ฑ forward ์˜ค๋ฒ„๋ ˆ์ด

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์„ค๊ณ„ ๊ฒฐ์ •์€, ๋ชจ๋“  ํŒจ์Šค๊ฐ€ mutable Scene์„ ์ „ํ˜€ ๋ชจ๋ฅธ๋‹ค๋Š” ์ ์ด๋‹ค. ํŒจ์Šค์˜ ์ž…๋ ฅ์€ immutable JFrameDesc ์™€ JRenderDB(GPU ๋ฆฌ์†Œ์Šค mirror)๋ฟ์ด๋ผ, ๊ฐ ํŒจ์Šค๋Š” ๊ฐ™์€ ์ž…๋ ฅ์— ๋Œ€ํ•ด ํ•ญ์ƒ ๊ฐ™์€ ์ถœ๋ ฅ์„ ๋‚ด๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜์— ๊ฐ€๊น๋‹ค. ๊ทธ ๋•๋ถ„์— ํŒจ์Šค ๋‹จ์œ„ ํ…Œ์ŠคํŠธ, ๊ฐ™์€ ํ”„๋ ˆ์ž„์˜ ๋ฐ˜๋ณต ์žฌ์ƒ(๋ฆฌํ”Œ๋ ˆ์ดยทํ—ค๋“œ๋ฆฌ์Šค), snapshotยทculling ๋‹จ๊ณ„์˜ ๋ณ‘๋ ฌํ™”๊ฐ€ ๊ตฌ์กฐ์ ์œผ๋กœ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

๋˜ํ•œ ๊ฐ ํŒจ์Šค๊ฐ€ ์ž๊ธฐ ์…ฐ์ด๋”ยทํŒŒ์ดํ”„๋ผ์ธ์„ lazyํ•˜๊ฒŒ ์ƒ์„ฑ(ensureResources)ํ•˜๊ณ , depthยทshadowยทgbuffer๊ฐ€ ๋™์ผํ•œ draw item ๋ชฉ๋ก(opaqueDrawItemIndices = frustum culling ๊ฒฐ๊ณผ)์„ ๊ณต์œ ํ•˜๋ฏ€๋กœ, ํŒจ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋น„์šฉ์ด "ํด๋ž˜์Šค ํ•˜๋‚˜ ์ถ”๊ฐ€" ์ˆ˜์ค€์œผ๋กœ ๋‚ฎ๋‹ค.

Depth Pre-Pass + Reverse-Z

๋ณธ๊ฒฉ์ ์ธ G-Buffer ๊ธฐ๋ก ์ „์—, ๋ถˆํˆฌ๋ช… ์˜ค๋ธŒ์ ํŠธ์˜ ๊นŠ์ด๋งŒ ๋จผ์ € ํ•œ ๋ฒˆ ๊ทธ๋ฆฐ๋‹ค. depth pre-pass๋กœ ์ตœ์ข… ๊นŠ์ด๋ฅผ ํ™•์ •ํ•ด ๋‘๋ฉด ์ดํ›„ G-Buffer / Lighting ํŒจ์Šค์—์„œ ๊ฐ€๋ ค์ง€๋Š” ํ”ฝ์…€์˜ ํ”ฝ์…€ ์…ฐ์ด๋” ๋น„์šฉ์„ ์ ˆ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๊ณผ์ •์—์„œ Reverse-Z๋ฅผ ์—”์ง„ ์ „์—ญ์˜ ๋‹จ์ผ ๊ทœ์•ฝ์œผ๋กœ ํ†ต์ผํ•œ ๊ฒƒ์ด ํŠน์ง•์ด๋‹ค. ๊นŠ์ด ๋น„๊ต ํ•จ์ˆ˜๋ฅผ GREATER, depth clear ๊ฐ’์„ 0(near = 1, far = 0)์œผ๋กœ ๋งž์ท„๊ณ , ์ด ๊ทœ์•ฝ์€ depth pre-pass๋ฟ ์•„๋‹ˆ๋ผ G-Buffer, shadow ortho ํˆฌ์˜, ๋น„๊ต ์ƒ˜ํ”Œ๋Ÿฌ, "์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๊ทธ๋ ค์ง„ ํ”ฝ์…€ ํŒ์ •"๊นŒ์ง€ ์ „๋ถ€ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋œ๋‹ค. depth๋ฅผ ๋‹ค๋ฃจ๋Š” ์ฝ”๋“œ ์–ด๋””์„œ๋“  "0 = far, ๋น„๊ต๋Š” GREATER"๊ฐ€ ์ผ๊ด€๋˜๊ฒŒ ์„ฑ๋ฆฝํ•˜๋ฏ€๋กœ, ํŒจ์Šค๋ฅผ ๋Š˜๋ ค๋„ ๊นŠ์ด ์ฒ˜๋ฆฌ์—์„œ ์‹ค์ˆ˜๊ฐ€ ๋ผ์–ด๋“ค ์—ฌ์ง€๊ฐ€ ์ ๋‹ค. ๋ถ€๊ฐ€์ ์œผ๋กœ ๋ถ€๋™์†Œ์ˆ˜์  depth ๋ถ„ํฌ๊ฐ€ ์›๊ฑฐ๋ฆฌ์—์„œ ์ด˜์ด˜ํ•ด์ ธ z-fighting๋„ ์ค„์–ด๋“ ๋‹ค.

depth pre-pass์™€ shadow pass๋Š” ๊ฒฐ๊ตญ ๊นŠ์ด๋งŒ ํ•„์š”ํ•˜๋ฏ€๋กœ ๋™์ผํ•œ depth_prepass.hlsl ์…ฐ์ด๋”๋ฅผ ๊ณต์œ ํ•œ๋‹ค. ํŒจ์Šค๊ฐ€ ๋Š˜์—ˆ์ง€๋งŒ ์…ฐ์ด๋” ์ฝ”๋“œ๋Š” ํ•œ ๋ฒŒ๋งŒ ์œ ์ง€๋œ๋‹ค.

// JDepthPass / JShadowPass ๋ชจ๋‘ ๊ฐ™์€ ์…ฐ์ด๋”๋ฅผ ์žฌ์‚ฌ์šฉ
_shader = renderContext->CreateShader(get_Engine_Shader_Path() + "\\depth_prepass.hlsl");
_pipeline = renderContext->CreatePipeline(
    _shader, /*alphaBlend*/ false, /*vertexInput*/ true, ...,
    /*depthWrite*/ D3D12_DEPTH_WRITE_MASK_ALL,
    /*depthFunc*/  D3D12_COMPARISON_FUNC_GREATER);  // reverse-Z

Cascade Shadow Map (CSM)

directional light์˜ ๊ด‘์—ญ ๊ทธ๋ฆผ์ž๋ฅผ ์œ„ํ•ด 4๋‹จ Cascade Shadow Map์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. ๊นŠ์ด๋Š” CASCADE_COUNT(4) ์Šฌ๋ผ์ด์Šค๋ฅผ ๊ฐ€์ง„ Texture2DArray ํ•œ ์žฅ์—, cascade๋ณ„ DSV๋กœ ๋‚˜๋ˆ  ๊ทธ๋ฆฐ๋‹ค.

Cascade ๋ถ„ํ•  โ€” ์นด๋ฉ”๋ผ ํ–‰๋ ฌ ํ•˜๋‚˜๋กœ ์ž๊ธฐ์™„๊ฒฐ

์นด๋ฉ”๋ผ์—์„œ ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์ด˜์ด˜ํ•œ ํ•ด์ƒ๋„๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ, ์‹œ์•ผ ๊ฑฐ๋ฆฌ๋ฅผ ๋น„์„ ํ˜• ๋น„์œจ๋กœ ๋‚˜๋ˆˆ๋‹ค.

// ๋ˆ„์  ๋น„์œจ โ€” ๊ฐ€๊นŒ์šด cascade์ผ์ˆ˜๋ก ์ข์€ ๊ตฌ๊ฐ„์„ ๋ฎ์Œ
constexpr float CASCADE_SPLIT_RATIOS[4] = { 0.05f, 0.16f, 0.42f, 1.0f };

์ด ๊ตฌํ˜„์˜ ํŠน์ง•์€ near/far ํ‰๋ฉด ๊ฐ’์ด๋‚˜ ๋ณ„๋„ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ”„๋ ˆ์ž„ ๋ฐ์ดํ„ฐ๋กœ ๋„˜๊ธฐ์ง€ ์•Š๊ณ , ์นด๋ฉ”๋ผ์˜ inverseViewProjection ํ•˜๋‚˜๋งŒ์œผ๋กœ ๋ชจ๋“  ๋ถ„ํ• ์„ ์œ ๋„ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค(self-contained). NDC ์ฝ”๋„ˆ๋ฅผ ์—ญํˆฌ์˜ํ•ด world-space ํ”„๋Ÿฌ์Šคํ…€ ์ฝ”๋„ˆ๋ฅผ ๊ตฌํ•˜๊ณ , ๊ฐ cascade ๊ตฌ๊ฐ„์„ ์ฝ”๋„ˆ ๋ณด๊ฐ„์œผ๋กœ ์ž˜๋ผ๋‚ธ๋‹ค.

// NDC ์ฝ”๋„ˆ โ†’ world-space ํ”„๋Ÿฌ์Šคํ…€ ์ฝ”๋„ˆ (reverse-Z: z=1 near, z=0 far)
corners.nearCorners[i] = XMVector3TransformCoord({ndcX, ndcY, 1.0f, 0.0f}, inverseViewProjection);
corners.farCorners[i]  = XMVector3TransformCoord({ndcX, ndcY, 0.0f, 0.0f}, inverseViewProjection);

์•ˆ์ •์ ์ธ light-space ๋ณผ๋ฅจ

๊ฐ cascade ์Šฌ๋ผ์ด์Šค์˜ 8๊ฐœ ์ฝ”๋„ˆ๋ฅผ ๊ฐ์‹ธ๋Š” bounding sphere๋กœ ์ง๊ต ํˆฌ์˜ ๋ณผ๋ฅจ์„ ์žก๋Š”๋‹ค. sphere ๊ธฐ๋ฐ˜์ด๋ผ ์นด๋ฉ”๋ผ๊ฐ€ ํšŒ์ „ํ•ด๋„ ๋ณผ๋ฅจ ํฌ๊ธฐ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์•„ ๊ทธ๋ฆผ์ž ๊ฐ€์žฅ์ž๋ฆฌ์˜ ๊นœ๋นก์ž„(shimmering)์ด ์ค„์–ด๋“ ๋‹ค. ์Šฌ๋ผ์ด์Šค ๋’ค์ชฝ(๋ผ์ดํŠธ ๋ฐฉํ–ฅ)์˜ caster๊นŒ์ง€ ๋‹ด๊ธฐ๋„๋ก ์—ฌ์œ (casterMargin)๋ฅผ ๋”ํ•˜๋ฉฐ, ์ง๊ต ํˆฌ์˜๋„ ์—”์ง„ ์ „์—ญ reverse-Z์— ๋งž์ถฐ near/far๋ฅผ ์Šค์™‘ํ•œ๋‹ค.

const XMMATRIX lightView = XMMatrixLookToLH(eye, lightDirection, up);
// reverse-Z(GREATER, clear 0)์— ๋งž์ถฐ near/far๋ฅผ ์Šค์™‘
const XMMATRIX lightProjection =
    XMMatrixOrthographicOffCenterLH(-radius, radius, -radius, radius, /*zFar*/ zFar, /*zNear*/ 0.0f);

์ƒ˜ํ”Œ๋ง โ€” ์…ฐ์ด๋”๊ฐ€ ์ƒ˜ํ”Œ๋Ÿฌ ์ข…๋ฅ˜๊นŒ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค

๋ผ์ดํŒ… ํŒจ์Šค์—์„œ๋Š” ํ”ฝ์…€์˜ ์นด๋ฉ”๋ผ ๊ฑฐ๋ฆฌ๋กœ cascade๋ฅผ ๊ณ ๋ฅธ ๋’ค 2ร—2 PCF๋กœ ์ƒ˜ํ”Œ๋งํ•œ๋‹ค. ๋น„๊ต ์ƒ˜ํ”Œ๋Ÿฌ๋ฅผ C++์—์„œ ๋งŒ๋“ค์–ด ๋„˜๊ธฐ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ์•ž์„œ ์„ค๋ช…ํ•œ ์ด๋ฆ„ ๊ทœ์•ฝ(Shadow)์— ๋”ฐ๋ผ ์…ฐ์ด๋” ๋ฆฌํ”Œ๋ ‰์…˜ ๋‹จ๊ณ„์—์„œ ์—”์ง„์ด reverse-Z ๋น„๊ต ์ƒ˜ํ”Œ๋Ÿฌ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•œ๋‹ค. ๋งต ๋ฐ– UV๋Š” border(0)์™€ ๋น„๊ต๋ผ ref >= 0 โ†’ ํ•ญ์ƒ lit์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.

Texture2DArray ShadowMap : register(t4);
SamplerComparisonState ShadowSampler : register(s0); // ์ด๋ฆ„์— Shadow โ†’ ๋น„๊ต ์ƒ˜ํ”Œ๋Ÿฌ ์ž๋™ ์ƒ์„ฑ

float referenceDepth = saturate(shadowPos.z + CascadeBiases[cascade]); // cascade๋ณ„ reverse-Z bias
shadow += ShadowMap.SampleCmpLevelZero(ShadowSampler, float3(uv, cascade), referenceDepth);

depth bias๋Š” world ๋‹จ์œ„๋กœ ํ•œ ๋ฒˆ๋งŒ ์ง€์ •ํ•˜๊ณ , cascade๋งˆ๋‹ค ์ž์‹ ์˜ zFar๋กœ ๋‚˜๋ˆ  reverse-Z depth ๋‹จ์œ„๋กœ ํ™˜์‚ฐํ•œ๋‹ค. ๋•๋ถ„์— ๊ฐ€๊นŒ์šด cascade์™€ ๋จผ cascade๊ฐ€ ์ผ๊ด€๋œ ๋‘๊ป˜์˜ bias๋ฅผ ๊ฐ–๋Š”๋‹ค.

Deferred PBR / Lighting

G-Buffer ๋ ˆ์ด์•„์›ƒ

MRT ํฌ๋งท ๋‚ด์šฉ
Albedo R8G8B8A8_UNORM base color (ร— material baseColor)
Normal R16G16B16A16_FLOAT world-space normal (0.5+0.5 ์ธ์ฝ”๋”ฉ)
Material R8G8B8A8_UNORM R=Roughness, G=Metallic, B=Occlusion
Depth D32_FLOAT reverse-Z depth (pre-pass์™€ ๊ณต์œ )

๋จธํ„ฐ๋ฆฌ์–ผ ํ…์Šค์ฒ˜๋Š” Bistro/glTF ์ปจ๋ฒค์…˜์˜ ORM ํŒจํ‚น(R=Occlusion, G=Roughness, B=Metalness) ์„ ๊ทธ๋Œ€๋กœ ์ฝ์–ด ํ•œ ๋ฒˆ์˜ ์ƒ˜ํ”Œ๋กœ ์„ธ ๊ฐ’์„ ์–ป๋Š”๋‹ค.

ํƒ„์  ํŠธ ์—†๋Š” ๋…ธ๋ฉ€ ๋งคํ•‘ (ํ™”๋ฉด ๊ณต๊ฐ„ ๋ฏธ๋ถ„)

๋…ธ๋ฉ€ ๋งคํ•‘์„ ์œ„ํ•ด ๋ฒ„ํ…์Šค ํƒ„์  ํŠธ๋ฅผ ๋”ฐ๋กœ ์ €์žฅยท์ž„ํฌํŠธํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋Œ€์‹  G-Buffer ํŒจ์Šค์—์„œ ํ™”๋ฉด ๊ณต๊ฐ„ ๋ฏธ๋ถ„(ddx/ddy)์œผ๋กœ cotangent frame์„ ์ฆ‰์„ ๊ตฌ์„ฑํ•ด ๋…ธ๋ฉ€ ๋งต์„ ์ ์šฉํ•œ๋‹ค(Schรผler์˜ cotangent frame). ๋ฉ”์‹œ ํฌ๋งท์— tangent ์ฑ„๋„์ด ์—†์–ด๋„ ๋…ธ๋ฉ€ ๋งคํ•‘์ด ๋™์ž‘ํ•˜๋ฏ€๋กœ FBX ์ž„ํฌํŠธ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ์ •์  ๋ ˆ์ด์•„์›ƒ์ด ๊ทธ๋งŒํผ ๋‹จ์ˆœํ•ด์ง„๋‹ค.

// ๋ฒ„ํ…์Šค ํƒ„์  ํŠธ ์—†์ด TBN ๊ตฌ์„ฑ. ddx/ddy๋Š” ๋ž˜์Šคํ„ฐํ™” ์ค‘์—๋งŒ ์œ ํšจํ•˜๋ฏ€๋กœ G๋ฒ„ํผ ํŒจ์Šค์—์„œ ๋…ธ๋ฉ€์„ ์™„์„ฑํ•œ๋‹ค.
float3 dp1 = ddx(worldPos);  float3 dp2 = ddy(worldPos);
float2 duv1 = ddx(uv);       float2 duv2 = ddy(uv);
float3 tangent   = cross(dp2, normal) * duv1.x + cross(normal, dp1) * duv2.x;
float3 bitangent = cross(dp2, normal) * duv1.y + cross(normal, dp1) * duv2.y;

BC5๋กœ ์••์ถ•๋œ ๋…ธ๋ฉ€ ๋งต์€ RG๋งŒ ์ €์žฅํ•˜๋ฏ€๋กœ Z๋Š” sqrt(1 - xยฒ - yยฒ)๋กœ ๋ณต์›ํ•œ๋‹ค.

๋ผ์ดํŒ… (Cook-Torrance PBR)

Lighting ํŒจ์Šค๋Š” full-screen triangle ํ•˜๋‚˜๋กœ ํ™”๋ฉด์„ ๋ฎ๊ณ , G-Buffer๋ฅผ Load๋กœ ์ง์ ‘ ์ฝ์–ด ํ”ฝ์…€๋ณ„ PBR์„ ๊ณ„์‚ฐํ•œ๋‹ค.

  • BRDF : GGX(๋ฒ•์„  ๋ถ„ํฌ) + Smith(๊ธฐํ•˜ ๊ฐ์‡ ) + Schlick Fresnel ์˜ Cook-Torrance ๋ชจ๋ธ.
  • ๋ผ์ดํŠธ : w <= 0 ์ด๋ฉด directional(๊ฐ์‡  ์—†์Œ), w > 0 ์ด๋ฉด point light๋กœ inverse-square + range windowing(UE/Frostbite ์Šคํƒ€์ผ) ๊ฐ์‡ ๋ฅผ ์ ์šฉํ•œ๋‹ค.
  • ๊ทธ๋ฆผ์ž : ๋ชจ๋“  directional light๊ฐ€ ์ฒซ directional ๊ธฐ์ค€ cascade shadow๋ฅผ ๊ณต์œ ํ•œ๋‹ค.
  • AO : occlusion(SSAO)์€ ๊ฐ„์ ‘๊ด‘(ambient)์—๋งŒ ์ ์šฉํ•˜๊ณ , ์ง์ ‘๊ด‘ ์ฐจํ๋Š” shadow map์ด ๋‹ด๋‹นํ•˜๋„๋ก ์—ญํ• ์„ ๋ถ„๋ฆฌํ–ˆ๋‹ค.
  • ํ†ค๋งคํ•‘ : ์ตœ์ข… ์ƒ‰์„ ACES filmic ๊ทผ์‚ฌ(Narkowicz 2015) ๋กœ ํ†ค๋งคํ•‘ํ•œ ๋’ค ๊ฐ๋งˆ ๋ณด์ •ํ•œ๋‹ค. Reinhard๋ณด๋‹ค ๋Œ€๋น„ยท์ฑ„๋„ ๋ณด์กด์ด ์ข‹๋‹ค.

์ „์—ญ reverse-Z ๊ทœ์•ฝ ๋•๋ถ„์—, "์•„๋ฌด๊ฒƒ๋„ ๊ทธ๋ ค์ง€์ง€ ์•Š์€ ํ”ฝ์…€(depth == 0 = far plane)"์„ ๋‹จ ํ•œ ๋ฒˆ์˜ ๋น„๊ต๋กœ ๊ฑธ๋Ÿฌ ๋ผ์ดํŒ…์„ ๊ฑด๋„ˆ๋›ด๋‹ค โ€” ๊นŠ์ด ๊ทœ์•ฝ์„ ํ†ต์ผํ•ด ๋‘” ํšจ๊ณผ๊ฐ€ ๋ผ์ดํŒ… ๋‹จ๊ณ„์—์„œ๋„ ๊ทธ๋Œ€๋กœ ์ด์–ด์ง„๋‹ค.

float depth = DepthBuffer.Load(int3(pixel, 0)).r;
if (depth <= 0.0f) return float4(albedo, alpha); // far plane = ๋ฏธ์ž‘์„ฑ ํ”ฝ์…€
...
color = ACESFilm(ambient + direct);
color = pow(saturate(color), 1.0 / 2.2);

์”ฌ ์บก์ฒ˜ ๊ธฐ๋ฐ˜ IBL + SSAO (Global Illumination)

์ง์ ‘๊ด‘(CSM)๋งŒ์œผ๋กœ๋Š” ๊ทธ๋ฆผ์ž ์˜์—ญ์ด ์ƒˆ๊นŒ๋งฃ๊ฒŒ ๋–จ์–ด์ง„๋‹ค. ๊ฐ„์ ‘๊ด‘์„ ์ฑ„์šฐ๊ธฐ ์œ„ํ•ด ์ •์  ์”ฌ์„ ์ง์ ‘ ์บก์ฒ˜ํ•ด ๊ตฝ๋Š” split-sum IBL๊ณผ ํ™”๋ฉด ๊ณต๊ฐ„ SSAO๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ์™ธ๋ถ€ HDRI๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  ์”ฌ ์ž์ฒด๋ฅผ ํ™˜๊ฒฝ๋งต์œผ๋กœ ์บก์ฒ˜ํ•˜๋ฏ€๋กœ ๋ฐ˜์‚ฌยท๊ฐ„์ ‘๊ด‘์ด ์‹ค์ œ ์žฅ๋ฉด๊ณผ ์ผ์น˜ํ•œ๋‹ค.

[๋กœ๋“œ ํ›„ 1ํšŒ bake]                              [๋งค ํ”„๋ ˆ์ž„]
 probe ์œ„์น˜์—์„œ ์”ฌ 6๋ฉด โ†’ HDR ํ๋ธŒ ์บก์ฒ˜
        โ”‚  (irradiance / prefiltered / BRDF LUT ์ƒ์„ฑ)
        โ–ผ                                        LightingPass:
 โ”Œโ”€ irradiance ํ๋ธŒ (diffuse GI) โ”€โ”               ambient = kDยทirradianceยทalbedo
 โ”œโ”€ prefiltered ํ๋ธŒ (specular)   โ”œโ”€โ”€์ƒ์ฃผ(์ƒ˜ํ”Œ๋งŒ)โ”€โ”€โ–ถ        + prefilteredยท(Fยทbrdf.x + brdf.y)
 โ””โ”€ BRDF LUT (Fํ•ญ ์ ๋ถ„)           โ”€โ”˜               (ร— SSAO)

1. ์”ฌ ์บก์ฒ˜ โ€” immutable ํ”„๋ ˆ์ž„ ๋ฐ์ดํ„ฐ์˜ ์žฌ์‚ฌ์šฉ

probe(์ฃผ ์นด๋ฉ”๋ผ) ์œ„์น˜์—์„œ 6๋ฉด์„ 90ยฐ FOVยทreverse-Z๋กœ HDR ํ๋ธŒ(R16G16B16A16F)์— ๋ Œ๋”ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„ ์„ค๊ณ„๊ฐ€ ๊ทธ๋Œ€๋กœ ์ด๋“์ด ๋œ๋‹ค โ€” ๊ฐ™์€ ์”ฌ์„ ๋ฉด๋งˆ๋‹ค JFrameDesc๋งŒ ์ƒˆ๋กœ ๊ตฌ์„ฑ(probe ์นด๋ฉ”๋ผ + ๋ฉด ๋ฐฉํ–ฅ + ํ๋ธŒ face ํƒ€๊ฒŸ)ํ•ด ๋™์ผํ•œ deferred ๊ฒฝ๋กœ๋ฅผ 6๋ฒˆ ๋Œ๋ฆฌ๋ฉด ๋์ด๋‹ค. IBL ์†Œ์Šค๋Š” linear์—ฌ์•ผ ํ•˜๋ฏ€๋กœ ์บก์ฒ˜ ๊ฒฝ๋กœ์—์„œ๋Š” ํ†ค๋งคํ•‘/๊ฐ๋งˆ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  linear HDR๋กœ ๊ธฐ๋กํ•œ๋‹ค.

2. ์ปจ๋ณผ๋ฃจ์…˜ โ€” compute ์—†์ด render-to-cube-face

์—”์ง„์— compute ํŒŒ์ดํ”„๋ผ์ธ์ด ์—†์–ด, ๋ชจ๋“  ์ปจ๋ณผ๋ฃจ์…˜์„ ํ’€์Šคํฌ๋ฆฐ ํŒจ์Šค๋กœ ํ๋ธŒ ๋ฉด์— ์ง์ ‘ ๋ Œ๋”ํ•ด ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

  • irradiance ํ๋ธŒ: ์บก์ฒ˜ ํ๋ธŒ๋ฅผ ์ฝ”์‚ฌ์ธ ๊ฐ€์ค‘ ์ ๋ถ„ โ†’ ์ €์ฃผํŒŒ diffuse GI (์ž‘์€ 32ยฒ ํ๋ธŒ๋กœ ์ถฉ๋ถ„)
  • prefiltered ํ๋ธŒ: roughness๋ณ„ GGX importance sampling์œผ๋กœ mip๋งˆ๋‹ค ํ”„๋ฆฌํ•„ํ„ฐ โ†’ roughness๊ฐ€ ํด์ˆ˜๋ก ํ๋ฆฐ ๋ฐ˜์‚ฌ
  • BRDF LUT: split-sum์˜ Fํ•ญ์„ (NdotV, roughness)๋กœ ์ ๋ถ„ํ•œ 2D LUT. ํ™˜๊ฒฝ๊ณผ ๋ฌด๊ด€ํ•˜๋ฏ€๋กœ ํ•œ ๋ฒˆ๋งŒ ๊ตฝ๋Š”๋‹ค.

3. ๋ผ์ดํŒ… โ€” split-sum ์ ์šฉ

float3 F   = FresnelSchlickRoughness(NdotV, f0, roughness);
float3 kD  = (1 - F) * (1 - metallic);
float3 diffuseIBL  = IrradianceMap.Sample(s, N).rgb * albedo;
float3 prefiltered = PrefilteredEnv.SampleLevel(s, reflect(-V, N), roughness * MaxMip).rgb;
float2 brdf        = BRDFLUT.Sample(sClamp, float2(NdotV, roughness)).rg;
float3 ambient = (kD * diffuseIBL + prefiltered * (F * brdf.x + brdf.y)) * ao;

๊ฒฐ๊ณผ ํ๋ธŒ 3์ข…์€ ๋Ÿฐํƒ€์ž„ ๋‚ด๋‚ด ์ƒ์ฃผํ•˜๊ณ  ๋งค ํ”„๋ ˆ์ž„ ํ…์Šค์ฒ˜ ์ƒ˜ํ”Œ๋งŒ ํ•œ๋‹ค โ€” ์ •์  ์”ฌ์ด๋ผ bake๋Š” 1ํšŒ๋ฉด ์ถฉ๋ถ„ํ•˜๊ณ  ๋Ÿฐํƒ€์ž„ ๋น„์šฉ์€ ๊ฑฐ์˜ 0์ด๋‹ค. ๋˜ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๊ฐ€ ์—†๋Š” ํ”ฝ์…€์—๋Š” ์ ˆ์ฐจ์  ํ•˜๋Š˜์„ ๊ทธ๋ ค, skybox ๋ฐฐ๊ฒฝ์ด์ž IBL ์ƒ๋ฐ˜๊ตฌ ๊ด‘์›์œผ๋กœ ๋™์‹œ์— ํ™œ์šฉํ–ˆ๋‹ค.

์—ฌ๊ธฐ์„œ๋„ ์—”์ง„์˜ ์ด๋ฆ„ ๊ทœ์•ฝ ๋ฐ”์ธ๋”ฉ์ด ์ด์–ด์ง„๋‹ค โ€” BRDF LUT์šฉ์œผ๋กœ ์ด๋ฆ„์— LUT๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด clamp ์ƒ˜ํ”Œ๋Ÿฌ๋ฅผ ์ž๋™ ์ƒ์„ฑํ•˜๋Š” ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•ด(๊ฐ€์žฅ์ž๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€), ์…ฐ์ด๋”๋Š” ์Šฌ๋กฏ/์ƒ˜ํ”Œ๋Ÿฌ ์„ค์ • ์—†์ด ์ด๋ฆ„๋งŒ ๋งž์ถ”๋ฉด ๋œ๋‹ค.

4. SSAO โ€” ๋ฐ์ดํ„ฐ ๋ฌธ์ œ๋ฅผ ์‹ค์‹œ๊ฐ„ ์ฐจํ๋กœ ์šฐํšŒ

์ด ์ž์‚ฐ์˜ "ORM" ํ…์Šค์ฒ˜๊ฐ€ ์‚ฌ์‹ค Specular ๋งต์ด๋ผ baked occlusion(R ์ฑ„๋„)์ด 0์— ๊ฐ€๊นŒ์› ๊ณ , ๊ทธ๋Œ€๋กœ ๊ณฑํ•˜๋ฉด ๊ฐ„์ ‘๊ด‘์ด ํ†ต์งธ๋กœ ์ฃฝ์–ด ๊ทธ๋ฆผ์ž๊ฐ€ ์ƒˆ๊นŒ๋งฃ๊ฒŒ ๋ณด์˜€๋‹ค. baked AO์— ์˜์กดํ•˜๋Š” ๋Œ€์‹  JSSAOPass๋กœ depthยทnormal์—์„œ ์‹ค์‹œ๊ฐ„ ์ฐจํ๋ฅผ ๊ณ„์‚ฐํ•ด ๊ฐ„์ ‘๊ด‘์—๋งŒ ๊ณฑํ•˜๋„๋ก ๋ฐ”๊ฟจ๋‹ค.

  • AO๋ฅผ ์ „์šฉ ํŒจ์Šค์—์„œ ๋‹จ์ผ ์ฑ„๋„ ํƒ€๊ฒŸ์— ๋ Œ๋”ํ•˜๊ณ , ๋ผ์ดํŒ…์—์„œ ๋ฐ•์Šค ๋ธ”๋Ÿฌ๋กœ ์ฝ์–ด ์•Œ๊ฐฑ์ด ๋…ธ์ด์ฆˆ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.
  • ์ƒ˜ํ”Œ ๋ฐ˜๊ฒฝ์„ ์›”๋“œ ๊ณต๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ์žก์•„ ํ™”๋ฉด ํ”ฝ์…€๋กœ ํ™˜์‚ฐํ•œ๋‹ค. ํ™”๋ฉด ๊ณ ์ • ํ”ฝ์…€ ๋ฐ˜๊ฒฝ์€ ์›๊ฑฐ๋ฆฌ์—์„œ ์›”๋“œ footprint๊ฐ€ ๊ณผ๋„ํ•˜๊ฒŒ ์ปค์ ธ ๊นŠ์ด๊ฐ€ ๋‹ค๋ฅธ ๋ฉด์„ ๊ฐ€๋กœ์งˆ๋Ÿฌ ์–ผ๋ฃฉ์ด ์ƒ๊ธฐ๋Š”๋ฐ, ์›”๋“œ ๊ธฐ์ค€์œผ๋กœ ๋‘๋ฉด ๊ฑฐ๋ฆฌ์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ผ์ •ํ•œ ์ฐจํ๊ฐ€ ๋œ๋‹ค.

์„ค๊ณ„ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„: ๋‹จ์ผ probe๋ผ ์œ„์น˜๋ณ„ ๋ฐ˜์‚ฌ ์‹œ์ฐจ(parallax)๋Š” ์—†๊ณ , 1-bounce ์ •์  ์บก์ฒ˜๋‹ค. ์ •์  ์”ฌ ์‡ผ์ผ€์ด์Šค์—์„  ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์œผ๋ฉฐ, ๋‹ค์ค‘ probeยท๋ฉ€ํ‹ฐ๋ฐ”์šด์Šค ์žฌbake๋กœ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋กœ ๋‚จ๊ฒจ ๋‘์—ˆ๋‹ค.

AI ์นœํ™”์  ์„ค๊ณ„

์ถ”ํ›„ AI Agent๋ฅผ ์—”์ง„์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์—ฌ, ์—”์ง„ ์•„ํ‚คํ…์ฒ˜๋ฅผ AI๊ฐ€ ์ดํ•ดํ•˜๊ณ  ํ™•์žฅํ•˜๊ธฐ ์‰ฌ์šด ํ˜•ํƒœ๋กœ ์„ค๊ณ„ํ–ˆ๋‹ค. Scene, Snapshot, RenderDB, Renderer, RenderPass์˜ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜๊ณ , ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๋‹จ๋ฐฉํ–ฅ์— ๊ฐ€๊น๊ฒŒ ๊ตฌ์„ฑํ•˜์—ฌ ๊ฐ ๋‹จ๊ณ„์˜ ์ฑ…์ž„๊ณผ ์ž…๋ ฅ/์ถœ๋ ฅ์„ ์ถ”์ ํ•˜๊ธฐ ์‰ฝ๋„๋ก ํ–ˆ๋‹ค. ๋˜ํ•œ ์ €์ˆ˜์ค€ DX12 API๋ฅผ JRenderContext, JCommandQueue, JGraphicResource ๊ฐ™์€ ์ž์ฒด API๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ, AI๊ฐ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ยท์ˆ˜์ •ํ•  ๋•Œ ๋ณต์žกํ•œ DX12 ์„ธ๋ถ€ ๊ตฌํ˜„๋ณด๋‹ค ์—”์ง„ ๋ ˆ๋ฒจ์˜ ๋ช…ํ™•ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.

Scene ์ €์žฅ ํฌ๋งท ์—ญ์‹œ AI ๋„๊ตฌ๊ฐ€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋„๋ก JSON ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑํ–ˆ๋‹ค. Scene์€ binary๊ฐ€ ์•„๋‹ˆ๋ผ entities / materials / meshes ๋กœ ๋ถ„๋ฆฌ๋œ ๋ช…์‹œ์  JSON ๊ตฌ์กฐ๋กœ ์ €์žฅ๋˜๋ฉฐ, ๊ฐ Entity๋Š” stableID, name, transform, camera, light, renderObjectComponent ์ฒ˜๋Ÿผ ์˜๋ฏธ ์žˆ๋Š” ํ•„๋“œ๋ช…์„ ๊ฐ€์ง„๋‹ค.

{
  "stableID": "ent_camera_001",
  "name": "MainCamera",
  "transform": { "translation": [0, 3, -5], "rotation": [0, 0, 0], "scale": [1, 1, 1] },
  "camera": { "primary": true, "nearP": 0.1, "farP": 1000.0 }
}

์ด ๊ตฌ์กฐ๋Š” ์—”์ง„ ๋‚ด๋ถ€์˜ Pool/Handle ๊ธฐ๋ฐ˜ ๋Ÿฐํƒ€์ž„ ๊ตฌ์กฐ์™€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค. ์‹คํ–‰ ์‹œ์—๋Š” ์„ฑ๋Šฅ ์ค‘์‹ฌ์˜ ๋ฐ์ดํ„ฐ ๋ฐฐ์น˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ €์žฅยทํŽธ์ง‘ ์‹œ์—๋Š” ๊ฐ€๋…์„ฑ๊ณผ ์ž๋™ํ™” ๊ฐ€๋Šฅ์„ฑ์„ ์šฐ์„ ํ•œ ๊ตฌ์กฐ์ด๋‹ค.

FBX ์ž„ํฌํ„ฐ + ํ…์Šค์ฒ˜ ์ฟ ํ‚น

JAssetImporter๋Š” OpenFBX๋ฅผ ์‚ฌ์šฉํ•ด FBX โ†’ ๋ฉ”์‹œ / ๋จธํ„ฐ๋ฆฌ์–ผ / ํ…์Šค์ฒ˜ / ์”ฌ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ณ„๋„ ์‹คํ–‰ ํŒŒ์ผ์ด๋‹ค. ํ…์Šค์ฒ˜๋Š” ์ž„ํฌํŠธ ์‹œ .jtex ์ปจํ…Œ์ด๋„ˆ(๋ฐ‰์ฒด์ธยท์••์ถ• ํฌ๋งท ํฌํ•จ)๋กœ ๊ตฌ์›Œ์ง€๊ณ , ๋Ÿฐํƒ€์ž„์€ ์ „์šฉ ๋ฆฌ๋”๋กœ ๊ทธ๋Œ€๋กœ GPU์— ์˜ฌ๋ฆฐ๋‹ค. ๋Ÿฐํƒ€์ž„์— FBX ์˜์กด์„ ๋‘์ง€ ์•Š๊ธฐ ์œ„ํ•ด ๋นŒ๋“œ์™€ ์ž„ํฌํŠธ๋ฅผ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

JAssetImporter <source.fbx> <projectDir>

๋ชจ๋“ˆ ๊ตฌ์„ฑ

src/
โ”œโ”€โ”€ engine/
โ”‚   โ”œโ”€โ”€ core/        JEngine, JEngineContext, JJobSystem, JPool, JHashFunction, JObject
โ”‚   โ”œโ”€โ”€ scene/       JScene, JTransformPool, JCameraPool, JLightPool,
โ”‚   โ”‚                JRenderObjectComponentPool, JSceneSerializer, JSceneHandle
โ”‚   โ”œโ”€โ”€ render/      JRenderer, JRenderServer, JRenderDB, JRenderSnapshotBuilder,
โ”‚   โ”‚                JCameraRenderQueueBuilder, JDrawItemCache, JMaterialFactory,
โ”‚   โ”‚                JCommandQueue, JSwapChain, JRenderContext, JRenderResource,
โ”‚   โ”‚                JGraphicResource, JRenderTarget, JGBuffer,
โ”‚   โ”‚                ํŒจ์Šค: SceneColor / Shadow / Depth / GBuffer / SSAO / Lighting / ForwardOverlay,
โ”‚   โ”‚                JShadowMap (CSM), JReflectionProbe (IBL)
โ”‚   โ”œโ”€โ”€ asset/       JMaterial, JMesh, JShader, JTextureFile (.jtex)
โ”‚   โ”œโ”€โ”€ platform/    JDevice
โ”‚   โ””โ”€โ”€ dx12/        JDx12Helper, d3dx12 wrapper
โ”œโ”€โ”€ client/
โ”‚   โ”œโ”€โ”€ editor/      JSceneManager, JScenePanel, JSceneBuilder, JImGuiLayer,
โ”‚   โ”‚                JFBXLoader, JAssetManager
โ”‚   โ””โ”€โ”€ OpenFBX/     vendored OpenFBX
tools/
โ””โ”€โ”€ JAssetImporter/  FBX โ†’ ํ”„๋กœ์ ํŠธ JSON/.jtex ๋ณ€ํ™˜๊ธฐ
samples/
โ””โ”€โ”€ GaussianSmoke/   ํŒŒํ‹ฐํด ์Šค๋ชจํฌ ๋ฐ๋ชจ (๋ณ„๋„ ์‹คํ–‰ ํŒŒ์ผ)
SampleProjects/
โ””โ”€โ”€ BistroExterior/  project.json ๊ธฐ๋ฐ˜ ์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ (deferred + CSM + IBL)
benchmark/           OOP / AoS / SoA / WorldMatrix ๋ฐ์ดํ„ฐ ๋ ˆ์ด์•„์›ƒ ๋น„๊ต (์˜ต์…˜)
third_party/
โ”œโ”€โ”€ nlohmann/json
โ””โ”€โ”€ imgui            ์—๋””ํ„ฐ UI

๋นŒ๋“œ ํƒ€๊ฒŸ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

ํƒ€๊ฒŸ ํ˜•ํƒœ ๋น„๊ณ 
Engine static lib DX12 / DXGI / D3DCompiler / WindowsCodecs
Client WIN32 exe ์—๋””ํ„ฐ/๋ทฐ์–ด๋ฅผ ๊ฒธํ•˜๋Š” ํ˜ธ์ŠคํŠธ ์‘์šฉ (ImGui)
JAssetImporter console exe FBX โ†’ ํ”„๋กœ์ ํŠธ/.jtex ๋ณ€ํ™˜ ๋„๊ตฌ
GaussianSmokeSample WIN32 exe ํŒŒํ‹ฐํด ์Šค๋ชจํฌ ๋ฐ๋ชจ
Benchmark console exe BUILD_BENCHMARK=ON ์˜ต์…˜. oneTBB FetchContent

๋นŒ๋“œ

์š”๊ตฌ ์‚ฌํ•ญ

  • Windows 10 ์ด์ƒ
  • Direct3D 12 ์ง€์› GPU (D3D_FEATURE_LEVEL_11_0+)
  • Visual Studio 2019/2022 + C++ desktop workload, Windows 10 SDK
  • ์„ ํƒ: Graphics Tools (D3D12 debug layer)

๋นŒ๋“œ ์ ˆ์ฐจ

cmake -S . -B build
cmake --build build --config Release

๋ฒค์น˜๋งˆํฌ๊นŒ์ง€ ๋นŒ๋“œํ•˜๋ ค๋ฉด:

cmake -S . -B build -DBUILD_BENCHMARK=ON
cmake --build build --config Release

Client๊ฐ€ Visual Studio์˜ ๊ธฐ๋ณธ ์‹œ์ž‘ ํ”„๋กœ์ ํŠธ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค.


์‹คํ–‰

Client ์‹คํ–‰ ์‹œ ๋ช…๋ น์ค„ ์˜ต์…˜:

Client.exe                       # ๊ธฐ๋ณธ ์ƒ˜ํ”Œ ์”ฌ (res/scene/sample.jscene.json)
Client.exe --new                 # ๋นˆ ์”ฌ์œผ๋กœ ์‹œ์ž‘ (-n)
Client.exe --scene <path>        # ํŠน์ • ์”ฌ ํŒŒ์ผ (-s)
Client.exe --project <path>      # ํ”„๋กœ์ ํŠธ ํด๋” (-p, project.json ํƒ์ƒ‰)
Client.exe <projectPath>         # ์œ„์น˜ ์ธ์ž๋„ ํ”„๋กœ์ ํŠธ ํด๋”๋กœ ํ•ด์„

์˜ˆ: ๋™๋ด‰๋œ Bistro ์ƒ˜ํ”Œ ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ

Client.exe --project SampleProjects/BistroExterior

FBX๋ฅผ ํ”„๋กœ์ ํŠธ๋กœ ์ž„ํฌํŠธ:

JAssetImporter <source.fbx> <projectDir>

<projectDir> ์•„๋ž˜์— scenes/, meshes/, materials/, textures/, shader/ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ๋จธํ„ฐ๋ฆฌ์–ผยท๋ฉ”์‹œ๋Š” JSON, ํ…์Šค์ฒ˜๋Š” .jtex๋กœ ์ €์žฅ๋œ๋‹ค.


์™ธ๋ถ€ ์ฝ”๋“œ

  • nlohmann/json โ€” third_party/nlohmann/
  • Dear ImGui โ€” third_party/imgui/ (์—๋””ํ„ฐ UI)
  • OpenFBX โ€” src/client/OpenFBX/
  • oneTBB โ€” ๋ฒค์น˜๋งˆํฌ ํƒ€๊ฒŸ ํ•œ์ •, CMake FetchContent๋กœ ๊ฐ€์ ธ์˜ด

๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ผ์ด์„ ์Šค๋ฅผ ๋”ฐ๋ฅธ๋‹ค.

About

A data-oriented DirectX 12 mini engine designed with an AI-agent-friendly architecture for structured state access, safe external control, and tool integration.

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages