전체글 48

7.4 도형 기하구조

원기둥 메시 생성하는 원기둥 중심은 원첨이고 y축 방향으로 서 있는 형태다. 모든 정점은 '고리'들에 있다. 더미의 개수가 stackCount라고 할 때 고리들은 총 stackCount + 1개이다. 그리고 각 고리는 sliceCount개의 고유한 정점들로 구성된다. 인접한 고리들의 반지름 차이는 이다. 최하단 고리가 0번째 라고 할 때, i번째 고리의 반지름은 이고, 높이는 가 된다. 여기서 △h는 더미 하나당 높이고 h는 원기둥의 높이이다. 그럼 여기서 조각의 정점 좌표와 인덱스는 아래와 같이 될 것이다. GeometryGenerator::MeshData GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float heigh..

DirectX 2022.01.06

7.3 패스별 상수 버퍼

std::unique_ptr PassCB = nullptr; 이 버퍼는 하나의 렌더링 패스 전체에서 변하지 않는 상수 자료를 저장한다. // FrameResource.h struct PassConstants { // 변하지 않는 상수 버퍼(시야 행렬, 투영 행렬, 시점 위치 등) 자료들. XMFLOAT4X4 View = MathHelper::Identity4x4(); XMFLOAT4X4 Proj = MathHelper::Identity4x4(); XMFLOAT4X4 InvView = MathHelper::Identity4x4(); XMFLOAT4X4 InvProj = MathHelper::Identity4x4(); XMFLOAT4X4 ViewProj = MathHelper::Identity4x4(); X..

DirectX 2022.01.06

7.2 렌더 항목

하나의 물체를 그리려면 버퍼 상수 등 묶고 설정하고 할 게 많다. 물체가 여러개이면 훨씬 복잡해진다. 물체를 그리는데 필요한 자료를 캡슐화하여 경량의 구조체로 만들면 편하다. 하나의 완전한 그리기 호출 명령을 렌더링 파이프라인에 제출하는 데 필요한 자료 집합을 이 책에서는 렌더 항목(render item)이라고 부른다. struct RenderItem { RenderItem() = default; // 이 행렬은 세계 공간에서의 물체의 위치, 방향, 크기를 결정. XMFLOAT4X4 World = MathHelper::Identity4x4(); // 개체 데이터가 바뀌어 상수 버퍼를 갱신해야 함을 나타내는 플래그. int NumFramesDirty = gNumFrameResource; // ObectCB..

DirectX 2022.01.06

7.1 프레임 자원

지금까지의 예제에서 사용해온 방식은 매 프레임마다 D3DApp::FlushCommandQueue()를 호출해 해당 프레임의 명령들이 모두 실행되기를 기다렸다. 이러한 방식은 비효율적이다. 한 프레임의 시작에서 CPU가 명령을 쓰는동안 GPU는 놀게된다. 한 프레임의 끝에서 GPU가 명령을 처리하는 동안 CPU는 놀게된다. 이 문제의 해결 방법은 매 프레임 CPU가 수정해야 하는 자원들을 순환 배열(circular array)로 관리하는 것이다. 이렇게 관리되는 자원들을 이 책에서는 프레임 자원(frame resource)라고 부르고, 일반적으로 사용한다. 순환 배열을 이용한 기법이란 프레임 n에서 CPU는 자원 배열을 훑으며 다음번 가용 프레임 자원(즉, GPU가 사용하지 않는 자원)을 찾는다. GPU가..

DirectX 2022.01.05

컨테이너와 반복자 살펴보기

표준 라이브러리 컨테이너는 원소를 값으로 처리한다(값 전달 방식). 다시 말해 원소의 복제본을 저장, 대입 연산자로 대입, 소멸자로 삭제한다. 그래서 항상 값을 복제할 수 있게 만들어야 한다. 원소를 레퍼런스로 처리하고 싶다면(레퍼런스 전달 방식) 원소를 그대로 넣지 않고 포인터를 사용해 저장한다. 이동 전용 타입, 즉 복제할 수 없는 타입도 컨테이너에 저장할 수 있지만, 이 때컨테이너의 연산 중 에러를 발생시킬 수 있다. 이동 전용 타입의 대표적인 예는 std::unique_ptr가 있다. 순차 컨테이너 vector deque list forward_list array 연관 컨테이너 map multimap set multiset 비정렬 연관 컨테이너(해시 테이블) unordered_map unorder..

C++ 2022.01.03

표준 라이브러리 둘러보기

C++ 프로그래머에게 가장 중요한 라이브러리는 C++ 표준 라이브러리다. 이 라이브러리 중 가장 핵심은 제네릭 컨테이너와 제네릭 알고리즘이다. 이 라이브러리는 원래 표준 템플릿 라이브러리라는 이름의 서드파티 라이브러리였다. 그래서 STL이라고 많이 부른다. 하지만 STL은 C++ 표준 용어가 아니다. 따라서 이 책은 STL이란 용어를 사용하지 않는다. 1. 코드 작성법 표준 라이브러리는 C++의 템플릿과 연산자 오버로딩 기능을 상당히 많이 사용한다. 2. C++ 표준 라이브러리 둘러보기 2.1 스트링 C++은 string 클래스를 기본으로 제공한다. 메모리 관리 뿐 아니라 인덱스 경계 검사, 대입과 비교, 추출, 부분화, 치환 등 다양한 기능을 제공한다. C++은 유니코드와 현지화도 지원한다. 그래서 다..

C++ 2022.01.03

6.10 기하구조 보조 구조체

하나의 기하구조 그룹을 정의하는 정점 버퍼와 색인 버퍼를 한데 엮는 편리한 보조 구조체를 설명한다. 이 구조체는 실제 정점 자료와 색인 자료를 시스템 메모리에 유지해서 CPU가 그 자료를 언제라도 읽을 수 있게 하는 역할도 한다. 선택(picking)이나 충돌 검출을 위해서는 CPU가 기하구조 자료에 접근해야 한다. 이 구조체는 버퍼 형식이나 보폭(stride) 같은 버택스 버퍼와 인덱스 버퍼의 주요 속성들도 담아 두며, 버퍼에 대한 뷰를 돌려주는 메서드도 제공한다. struct SubMeshGeometry { UINT IndexCount = 0; UINT StartIndexLocation = 0; INT BaseVertexLocation = 0; // 기하구조의 경계 상자(bounding box) 뒷 ..

DirectX 2022.01.03

6.9 파이프라인 상태 객체

객체들을 실제로 사용하기 위해 렌더링 파이프라인에 묶는 방법은 아직 나오지 않았다. 렌더링 파이프라인의 상태를 제어하는 대부분의 객체는 파이프라인 상태 객체(pipeline state object, PSO)라고 부르는 집합체(aggregate)를 통해서 지정된다. ID3D12PipelineState 인터페이스를 대표적으로 사용한다. PSO를 생성하기 위해 D3D12_GRAPHICS_PIPELINE_STATE_DESC 구조체를 채워야 한다. void BoxApp::BuildPSO() { D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; ZeroMemory(&psoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); psoDesc.p..

DirectX 2022.01.03

6.8 래스터화기 상태

래스터화 단계는 래스터화기 상태(rasterizer state)를 통해 구성한다. 대표적으로 D3D12_RASTERIZER_DESC 구조체를 사용한다. https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_rasterizer_desc D3D12_RASTERIZER_DESC (d3d12.h) - Win32 apps Describes rasterizer state. docs.microsoft.com 다음 네 멤버 이외에는 고급 기법이거나 자주 사용하지 않으므로 SDK 문서화를 참고하길 바란다. 1. FillMode: 와이어프레임(wireframe) 렌더링을 위해서는 D3D12_FILL_WIREFRAME을, 면의 속을 채운(solid)..

DirectX 2022.01.03

I/O 완전 분석

C의 printf() scanf()는 굉장히 유연한 I/O 매커니즘이다. 이 함수는 정수나 문자 타입, 부동 소수점 타입, 스트링 타입만 지원한다는 한계가 있지만 이스케이프 코드와 서식 지정자로 다양한 포맷의 데이터를 읽거나 출력하는 기능을 제공한다. 하지만 printf() scanf()를 뛰어난 I/O 시스템이라 보기엔 아쉬운 점이 있다. 무엇보다 에러 처리 기능을 제공하지 않으며, 커스텀 데이터 타입을 다룰 정도로 유연하지 않고, C++와 같은 객체지향과 어울리지도 않다. C++은 스트림(stream) 이라는 정교한 입출력 메커니즘을 제공한다. 스트림은 I/O를 유연하고 객체지향적으로 처리한다. cout 스트림을 컨베이어 밸트에 비유할 수 있다. 스트림에 변수를 올려보내면 사용자 화면인 콘솔에 표시된..

C++ 2022.01.01