기존에는 CubeMap은 무조건 dds파일로, 일반 텍스쳐는 다른 확장자로 로드하는 이상한 구조였다.

이번엔, 확장자 별로 로드방식을 다르게 하되, 큐브맵 텍스쳐와 일반적인 디퓨즈 텍스쳐를 구분하여 로드하도록 수정할 것이다.

void ResourceManager::LoadTexture(const std::string& _TextureName, ETextureType _Type)
{
	std::string Format = GetFormat(_TextureName);

	if (Format == "dds")
	{
		LoadDDSTexture(_TextureName, _Type);
	}
	else
	{
		LoadGeneralTexture(_TextureName, _Type);
	}
}

 

먼저 LoadTexture 함수를 위와 같이 수정하였다.

파일 이름에서 확장자를 탐색한 뒤, 확장자를 기준으로 dds라면 LoadDDSTexture함수를 호출하였고 아니라면 LoadGeneralTexture함수를 호출하였다.

 

이렇게 확장자를 구분한 이유는 stb 라이브러리는 dds파일을 지원하지 않는 것도 있고, dds파일의 경우 마이크로 소프트에서 다이렉트X에 맞게 만든 확장자이다 보니 DirectX 함수를 사용하는 것이 여러모로 좋을 것 같기 때문이기도 하다.

 

std::string ResourceManager::GetFormat(const std::string& _FileName)
{
    int Count = 0;

    for (int i = _FileName.size() - 1; i >= 0; i--)
    {
        if (_FileName[i] == '.')
        {
            break;
        }

        Count++;
    }

    std::string Format = _FileName.substr(_FileName.size() - Count, Count);

    return Format;
}

 

GetFormat함수 내부는 위와 같다.

void ResourceManager::LoadDDSTexture(const std::string& _TextureName, ETextureType _Type)
{
    Microsoft::WRL::ComPtr<ID3D11Texture2D> Texture;
    Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> SRV;

    std::wstring Path = L"../Texture/";
    std::wstring TextureName;
    TextureName.assign(_TextureName.begin(), _TextureName.end());

    Path += TextureName;

    UINT Flag = 0;

    if (_Type == ETextureType::CubeMap)
    {
        Flag = D3D11_RESOURCE_MISC_TEXTURECUBE;
    }

    HRESULT Result = DirectX::CreateDDSTextureFromFileEx(
        EngineBase::GetInstance().GetDevice().Get(), Path.c_str(), 0, D3D11_USAGE_DEFAULT,
        D3D11_BIND_SHADER_RESOURCE, 0,
        Flag,
        DirectX::DDS_LOADER_FLAGS(false), (ID3D11Resource**)Texture.GetAddressOf(),
        SRV.GetAddressOf(), nullptr);

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

    TextureData NewTextureData;
    NewTextureData.Texture = Texture;
    NewTextureData.ShaderResourceView = SRV;

    LoadedTextures.insert({ _TextureName, NewTextureData });
}

 

위 코드는 DDS 파일 로드 함수이다.

Cube텍스쳐의 경우, Flag를 설정하여 SRV를 Cube텍스쳐로 생성하도록 하였다.

void ResourceManager::LoadGeneralTexture(const std::string& _TextureName, ETextureType _Type)
{
    std::string Path = "../Texture/";
    Path += _TextureName;

    int Width = 0;
    int Height = 0;
    int Channels = 0;

    unsigned char* LoadedImage = stbi_load(Path.c_str(), &Width, &Height, &Channels, 0);
    if (LoadedImage == nullptr)
    {
        std::cout << "Image Load Failed" << std::endl;
        return;
    }

    std::vector<uint8_t> Image;

    Image.resize(Width * Height * Channels);
    memcpy(Image.data(), LoadedImage, Image.size() * sizeof(uint8_t));

    Microsoft::WRL::ComPtr<ID3D11Texture2D> Texture;
    Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> SRV;

    D3D11_TEXTURE2D_DESC TexDesc = {};
    TexDesc.Width = Width;
    TexDesc.Height = Height;
    TexDesc.MipLevels = TexDesc.ArraySize = 1;
    TexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    TexDesc.SampleDesc.Count = 1;
    TexDesc.Usage = D3D11_USAGE_IMMUTABLE;
    TexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;

    if(_Type == ETextureType::CubeMap)
    {
        TexDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
    }

    D3D11_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = Image.data();
    InitData.SysMemPitch = TexDesc.Width * sizeof(uint8_t) * Channels;

    HRESULT Result = EngineBase::GetInstance().GetDevice()->CreateTexture2D(&TexDesc, &InitData, Texture.GetAddressOf());
    if (Result != S_OK)
    {
        std::cout << "CreateTexture2D failed " << std::endl;
        return;
    }

    Result = EngineBase::GetInstance().GetDevice()->CreateShaderResourceView(Texture.Get(), nullptr, SRV.GetAddressOf());
    if (Result != S_OK)
    {
        std::cout << "CreateTexture2D failed " << std::endl;
        return;
    }

    TextureData NewTextureData;
    NewTextureData.Texture = Texture;
    NewTextureData.ShaderResourceView = SRV;

    stbi_image_free(LoadedImage);

    LoadedTextures.insert({ _TextureName, NewTextureData });

    return;
}

 

위 코드는 DDS를 제외한 나머지 텍스쳐를 로드하는 코드이다.

stb라이브러리를 사용해서 로드하고 있으며, DDS파일과 동일하게 ETextureType에 따라 Flag를 설정하여 Cube텍스쳐는 그에 맞게 로드하도록 하였다.

 

 

기존과 동일하게 잘 렌더링이 된다!

 

(나중에 알게된 사실이지만 큐브맵 텍스쳐는 DDS만 된다고 한다. png나 jpg등으로 사용하려면 직접 조립해야한다고...)

+ Recent posts