쉐이더 파일의 경우, 동일한 쉐이더가 여러번 컴파일될 필요가 없기 때문에 EngineBase에 쉐이더 파일을 따로 저장하도록 하였다.

 

그리고 쉐이더를 생성할 때, EngineBase에서 해당 쉐이더가 이미 존재하는지를 판단한 뒤 없을때에만 새로 생성하고 컴파일하도록 하였다.

 

struct VertexShaderData
{
    Microsoft::WRL::ComPtr<ID3D11VertexShader> VertexShader;
    Microsoft::WRL::ComPtr<ID3D11InputLayout> InputLayout;
};

 

이렇게, 버텍스쉐이더와 인풋 레이아웃을 함께 담는 구조체를 하나 선언하였다.

std::unordered_map<const std::wstring, VertexShaderData> VertexShaders;

 

EngineBase내부엔 위와 같은 자료구조를 선언하여,  버텍스 쉐이더 데이터를 저장하도록 하였다.

key는 쉐이더 파일의 이름이다.

 

BOOL EngineBase::CreateVertexShader(const std::wstring& _ShaderFileName, std::vector<D3D11_INPUT_ELEMENT_DESC> _InputElement)
{
    if (VertexShaders.find(_ShaderFileName) != VertexShaders.end())
    {
        std::cout << "Don't try to Create existed VertexShader" << std::endl;
        return TRUE;
    }

    Microsoft::WRL::ComPtr<ID3DBlob> ShaderBlob;
    Microsoft::WRL::ComPtr<ID3DBlob> ErrorBlob;

    HRESULT Result =
        D3DCompileFromFile(_ShaderFileName.c_str(), 0, 0, "main", "vs_5_0", 0, 0, &ShaderBlob, &ErrorBlob);

    if (Result != S_OK) 
    {
        if ((Result & D3D11_ERROR_FILE_NOT_FOUND) != 0) 
        {
            std::cout << "File not found." << std::endl;
        }

        if (ErrorBlob)
        {
            std::cout << "Shader compile error\n" << (char*)ErrorBlob->GetBufferPointer() << std::endl;
        }

        return FALSE;
    }

    Microsoft::WRL::ComPtr<ID3D11VertexShader> NewVertextShader;

    Result = 
        EngineBase::GetInstance().GetDevice()->CreateVertexShader(ShaderBlob->GetBufferPointer(), ShaderBlob->GetBufferSize(), NULL,
        &NewVertextShader);

    if (Result != S_OK)
    {
        std::cout << "CreateVertexShader() failed" << std::endl;
        return FALSE;
    }

    Microsoft::WRL::ComPtr<ID3D11InputLayout> _InputLayOut;
    if (!CreateInputLayOut(_InputElement, _InputLayOut, ShaderBlob))
    {
        return FALSE;
    }

    VertexShaders.insert({ _ShaderFileName, {NewVertextShader, _InputLayOut} });

    return TRUE;
}

 

먼저, 지금 만들고자 하는 쉐이더가 이미 생성되어 있다면 따로 만들지 않도록 해주었다.

이후, 입력된 파일 이름을 기반으로 쉐이더 컴파일을 실행하였고 파일이 있는지 없는지, 혹은 다른 오류로 컴파일이 실패하였는지 확인 과정을 거쳐주었다.

 

다음은 컴파일된 쉐이더를 통해 버텍스 쉐이더를 생성해주었다.

버텍스 쉐이더를 만들었으면, 인풋 레이아웃도 만들어야 하기 때문에, 인풋 레이아웃도 만들어주었다.

 

마지막으로, VertexShaders 자료구조에 데이터를 삽입해주었다.

BOOL EngineBase::CreateInputLayOut(std::vector<D3D11_INPUT_ELEMENT_DESC> _InputElement, Microsoft::WRL::ComPtr<ID3D11InputLayout> _InputLayOut, Microsoft::WRL::ComPtr<ID3DBlob> _ShaderBlob)
{
    HRESULT Result = 
    EngineBase::GetInstance().GetDevice()->CreateInputLayout(_InputElement.data(), UINT(_InputElement.size()),
        _ShaderBlob->GetBufferPointer(), _ShaderBlob->GetBufferSize(),
        &_InputLayOut);

    if (Result != S_OK)
    {
        std::cout << "CreateInputLayOut() failed" << std::endl;
        return FALSE;
    }

    return TRUE;
}

인풋 레이아웃 생성 함수는 위와 같다. 간단하다.

 

std::unordered_map<const std::wstring, Microsoft::WRL::ComPtr<ID3D11PixelShader>> PixelShaders;

픽셀 쉐이더에 대해서도 자료구조를 생성해주었다.

 

BOOL EngineBase::CreatePixelShader(const std::wstring& _ShaderFileName)
{
    Microsoft::WRL::ComPtr<ID3DBlob> ShaderBlob;
    Microsoft::WRL::ComPtr<ID3DBlob> ErrorBlob;

    HRESULT Result =
        D3DCompileFromFile(_ShaderFileName.c_str(), 0, 0, "main", "ps_5_0", 0, 0, &ShaderBlob, &ErrorBlob);
    
    if (Result != S_OK)
    {
        if ((Result & D3D11_ERROR_FILE_NOT_FOUND) != 0)
        {
            std::cout << "File not found." << std::endl;
        }

        if (ErrorBlob)
        {
            std::cout << "Shader compile error\n" << (char*)ErrorBlob->GetBufferPointer() << std::endl;
        }

        return FALSE;
    }

    Microsoft::WRL::ComPtr<ID3D11PixelShader> NewPixelShader;

    Result = 
    EngineBase::GetInstance().GetDevice()->CreatePixelShader(ShaderBlob->GetBufferPointer(), ShaderBlob->GetBufferSize(), NULL,
        &NewPixelShader);

    if (Result != S_OK)
    {
        std::cout << "CreatePixelShader() failed" << std::endl;
        return FALSE;
    }

    PixelShaders.insert({ _ShaderFileName, NewPixelShader });

    return TRUE;
}

 

픽셀 쉐이더도 버텍스 쉐이더와 동일하게 만들어주었다.

이제, 조금만 더 하면 화면에 정육면체를 띄울 수 있을 것 같다...!

+ Recent posts