그래픽스/DirectX 12

[DirectX 12 3D게임 입문] Chapter 7.9: Direct3D의 그리기 연산 제2부 - 연습문제

KANTAM 2023. 11. 21. 22:24

1. 도형 예제를, GeometryGenerator::CreateSphere 대신 GeometryGeneartor::CreateGeosphere를 사용하도록 수정하고, 세부 수준을 0, 1, 2, 3으로 바꿔보자.

세부 수준 0
세부 수준 3

 

3. 8장의 두개골 메시를 적재해서 렌더링해보자. 

8장의 연습문제 'LitColumns' 예제 폴더의 Models/Skull.txt는 정점 목록과 색인 목록이 들어있다. 

skull.txt

 

일단 이 두개골의 정점과 색인을 읽어서 정점 버퍼와 색인 버퍼를 만들어야 한다. 그 후, 기하구조 보조 구조체인 MeshGeometry를 채워서 멤버 데이터인 Geometries에 집어넣는다. 

void ShapesApp::BuildSkullGeometry()
{
    std::ifstream fin("Models/skull.txt");

    if (!fin)
    {
        MessageBox(0, L"Models/skull.txt not found.", 0, 0);
        return;
    }

    UINT vcount = 0;
    UINT tcount = 0;
    std::string ignore;

    fin >> ignore >> vcount;
    fin >> ignore >> tcount;
    fin >> ignore >> ignore >> ignore >> ignore;

    std::vector<Vertex> vertices(vcount);
    for (UINT i = 0; i < vcount; ++i)
    {
        fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
        fin >> ignore >> ignore >> ignore;
        // fin >> vertices[i].Color.x >> vertices[i].Color.y >> vertices[i].Color.z;
    }

    fin >> ignore;
    fin >> ignore;
    fin >> ignore;

    std::vector<std::int32_t> indices(3 * tcount);
    for (UINT i = 0; i < tcount; ++i)
    {
        fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2];
    }

    fin.close();

    auto vbByteSize = vertices.size() * sizeof(Vertex);     // auto로 받는게 편하다.
    auto ibByteSize = indices.size() * sizeof(UINT);

    auto geo = std::make_unique<MeshGeometry>();
    geo->Name = "skull";

    ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
    CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);

    ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
    CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);

    geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);

    geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);

    geo->VertexByteStride = sizeof(Vertex);
    geo->VertexBufferByteSize = static_cast<UINT>(vbByteSize);
    geo->IndexFormat = DXGI_FORMAT_R32_UINT;                // IndexFormat에 주의
    geo->IndexBufferByteSize = static_cast<UINT>(ibByteSize);

    SubmeshGeometry skullmesh;
    skullmesh.IndexCount = static_cast<UINT>(indices.size());
    skullmesh.StartIndexLocation = 0;
    skullmesh.BaseVertexLocation = 0;

    geo->DrawArgs["skull"] = skullmesh;

    mGeometries[geo->Name] = std::move(geo);
}

 

그리고 집어넣은 데이터로 렌더 항목을 만든다. 

void ShapesApp::BuildRenderItems()
{
    ...
    auto skullRitem = std::make_unique<RenderItem>();
    XMStoreFloat4x4(&skullRitem->World, XMMatrixTranslation(0.0f, 2.0f, 0.0f));
    skullRitem->ObjCBIndex = 2;
    skullRitem->Geo = mGeometries["skull"].get();
    skullRitem->PrimitiveType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
    skullRitem->IndexCount = skullRitem->Geo->DrawArgs["skull"].IndexCount;
    skullRitem->StartIndexLocation = skullRitem->Geo->DrawArgs["skull"].StartIndexLocation;
    skullRitem->BaseVertexLocation = skullRitem->Geo->DrawArgs["skull"].BaseVertexLocation;
    mAllRitems.push_back(std::move(skullRitem));
    
    // 두개골이 렌더 항목에 추가되어 인덱스가 3부터 시작
    UINT objCBIndex = 3;
    // 총 5번 원기둥과 구를 각각 2개씩 추가하여 총 각각 10개씩 mAllRitems에 넣어진다.
	for(int i = 0; i < 5; ++i)
    {
    	// 원기둥과 구 입력
    }
}