반응형

이번 단계에서는 씬을 별도 텍스처(오프스크린 RT)에 렌더링하고, 그 텍스처를 ImGui의 Viewport 패널 안에 이미지로 표시합니다.


프레임 흐름

[매 프레임]
 ├─ (패널 크기 변경 요청 시) WaitIdle → RT Resize
 ├─ ImGui NewFrame + UI 구성     ← Viewport 패널 크기를 읽고 ImGui::Image(SRV) 기록
 ├─ Renderer::BeginFrame         ← 백버퍼 PRESENT → RT, Clear
 ├─ ViewportRT.Begin             ← 텍스처 PSR → RT, Clear(color/depth), Viewport/Scissor
 │    └─ SceneRenderer::Render   ← 큐브 Draw
 ├─ ViewportRT.End               ← 텍스처 RT → PSR (셰이더에서 읽을 수 있게)
 ├─ Renderer::BindBackBuffer     ← 다시 백버퍼를 타깃으로
 ├─ ImGui Render                 ← Viewport 패널이 RT 텍스처를 샘플링
 └─ Renderer::EndFrame           ← RT → PRESENT, Execute, Present

 

핵심은 같은 텍스처가 한 프레임 안에서 두 가지 역할을 한다는 점입니다.
씬 패스에서는 RenderTarget으로 쓰이고, UI패스에서는 ShaderResource로 읽힙니다.

그래서 두 패스 사이에 리소스 배리어(RT<->PSR)가 반드시 필요합니다.


RenderTarget (Engine/RHI/RenderTarget)

항목 내용
소유 리소스 컬러 텍스처(R8G8B8A8_UNORM), 깊이 텍스처(D32_FLOAT)
디스크립터 RTV(RTV힙), DSV(DSV힙), SRV(shader-visible CBV_SRV_UAV 힙)
기본 상태 컬러는 PIXEL_SHADER_RESOURCE, 깊이는 DEPTH_WRITE
Init 디스크립터를 한 번만 Allocate해 두고 재사용
Resize(w, h) 텍스처 재생성 후 같은 슬롯에 RTV/DSV/SRV를 다시 기록
Begin / End 배리어, 바인딩, Clear,Viewport / Scissor 설정

Optimized Clear Value: 리소스 생성 시 D3D12_CLEAR_VALUE에 넣은 색과 실제 Clear 색을 맞춰야 경고가 나지 않고 Fast Clear 최적화가 적용됩니다.

리사이즈 시 동기화: GPU가 아직 사용 중인 텍스처를 해제하면 안 되므로, 현재는 WaitIdle 후 재 생성합니다.


Renderer 확장

RTV힙(64개)과 DSV힙(16개)을 추가했습니다. 둘 다 non-shader-visible입니다.

BindBackBuffer()는 씬 패스가 끝난 뒤 다시 백버퍼를 렌더 타킷으로 지정합니다.


SceneRenderer (Engine/Renderer/SceneRenderer)

루트 시그니처: Root Constants 16개 (b0=MVP행렬)만 사용합니다(가장 단순한 형태).

PSO: 기본 Rasterizer/Blend/Depth, RTV는 R8G8B8A8, DSV는 D32입니다.

지오메트리: 큐브 8개 정점에 정점 색을 넣고, 인덱스 36개(R16_UINT)를 씁니다.

MVP: Wolrd(회전) * LookAtLH * PerspectiveFovLH를 Transpose해서 전달합니다.aspect는 RT 크기 기준으로 계산합니다.


Shader 컴파일 헬퍼 (Engine/RHI/Shader)

D3DCompileFromFile을 래핑했습니다. Debug 빌드에서는 DEBUG | SKIP_OPTIMIZATION 을 켭니다.

에러 메시지를 OutputDebugStringA로 출력 창에 남기고, 예외로도 던집니다.

셰이더 경로는 CMake에서 BAEK_SHADER_DIR="${CMAKE_SOURCE_DIR}/Shaders/" 로 주입합니다. 이렇게 하면 실행 위치(working dir)와 무관하게 셰이더를 찾을 수 있습니다.


에디터 UI

Viewport 패널: 패딩을 0으로 두고, GetContentRegionAvail()로 얻은 크기를 다음 프레임 RT 크기로 요청합니다. 표시는 ImGui::Image(SRV GPU handle)로 합니다.

DockBuilder 기본 레이아웃: imgui.ini가 없을 때만 Viewport를 가운데, Status를 오른쪽 22%에 배치합니다.이후 사용자가 바꾼 배치는 ini에 저장돼 유지됩니다.

 

 


트러블 슈팅

 

Basic.hlsl(1,1): error X3000: Illegal character -> .editorconfig가 hlsl을 UTF-8 BOM으로 저장. FXC는 BOM을 처리하지 못함

해결(.editorconfig으로 hlsl만 utf-8로 저장)

root = true

[*.{h,hpp,cpp,txt,json}]
charset = utf-8-bom

[*.hlsl]
charset = utf-8

 

결과

반응형

+ Recent posts