Skip to content

Instantly share code, notes, and snippets.

@yorung
Last active August 29, 2015 14:27
Show Gist options
  • Save yorung/bacf31c7107cdbd2a7e4 to your computer and use it in GitHub Desktop.
Save yorung/bacf31c7107cdbd2a7e4 to your computer and use it in GitHub Desktop.
DDS Loader
struct DDSHeader {
uint32_t h3[3];
int h, w;
uint32_t h2[2];
int mipCnt;
uint32_t h13[13];
uint32_t fourcc, bitsPerPixel, rMask, gMask, bMask, aMask, caps1, caps2;
bool IsCubeMap() const { return caps2 == 0xFE00; }
int GetArraySize() const { return IsCubeMap() ? 6 : 1; }
int GetMipCnt() const { return std::max(mipCnt, 1); }
};
static void ArrangeRawDDS(void* img, int size)
{
const DDSHeader* hdr = (DDSHeader*)img;
DWORD rShift, gShift, bShift, aShift;
_BitScanForward(&rShift, hdr->rMask);
_BitScanForward(&gShift, hdr->gMask);
_BitScanForward(&bShift, hdr->bMask);
_BitScanForward(&aShift, hdr->aMask);
std::for_each((uint32_t*)img + 128 / 4, (uint32_t*)img + size / 4, [&](uint32_t& im) {
im = ((hdr->aMask & im) >> aShift << 24) + ((hdr->bMask & im) >> bShift << 16) + ((hdr->gMask & im) >> gShift << 8) + ((hdr->rMask & im) >> rShift);
} );
}
static ComPtr<ID3D11ShaderResourceView> LoadDDSTexture(const char* name, ivec2& texSize)
{
int size;
ComPtr<ID3D11ShaderResourceView> srv;
void* img = LoadFile(name, &size);
if (!img) {
aflog("LoadDDSTexture failed! %s", name);
return 0;
}
const DDSHeader* hdr = (DDSHeader*)img;
DXGI_FORMAT format;
int (*pitchCalcurator)(int, int) = nullptr;
switch (hdr->fourcc) {
case 0x31545844: //'1TXD':
format = DXGI_FORMAT_BC1_UNORM;
pitchCalcurator = [](int w, int h) { return ((w + 3) / 4) * ((h + 3) / 4) * 8; };
break;
case 0x33545844: //'3TXD':
format = DXGI_FORMAT_BC2_UNORM;
pitchCalcurator = [](int w, int h) { return ((w + 3) / 4) * ((h + 3) / 4) * 16; };
break;
case 0x35545844: //'5TXD':
format = DXGI_FORMAT_BC3_UNORM;
pitchCalcurator = [](int w, int h) { return ((w + 3) / 4) * ((h + 3) / 4) * 16; };
break;
default:
ArrangeRawDDS(img, size);
format = DXGI_FORMAT_R8G8B8A8_UNORM;
pitchCalcurator = [](int w, int h) { return w * h * 4; };
break;
}
texSize.x = hdr->w;
texSize.y = hdr->h;
int arraySize = hdr->GetArraySize();
int mipCnt = hdr->GetMipCnt();
CD3D11_TEXTURE2D_DESC desc(format, hdr->w, hdr->h, arraySize, hdr->GetMipCnt(), D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1, 0, hdr->IsCubeMap() ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0);
CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc(hdr->IsCubeMap() ? D3D_SRV_DIMENSION_TEXTURECUBE : D3D_SRV_DIMENSION_TEXTURE2D, desc.Format, 0, -1);
std::vector<D3D11_SUBRESOURCE_DATA> r;
int offset = 128;
for (int a = 0; a < arraySize; a++) {
for (int m = 0; m < mipCnt; m++) {
int w = std::max(1, hdr->w >> m);
int h = std::max(1, hdr->h >> m);
r.push_back({ (char*)img + offset, (uint32_t)pitchCalcurator(w, 1), 0 });
offset += pitchCalcurator(w, h);
}
}
ComPtr<ID3D11Texture2D> tex;
deviceMan11.GetDevice()->CreateTexture2D(&desc, &r[0], &tex);
deviceMan11.GetDevice()->CreateShaderResourceView(tex.Get(), &srvDesc, &srv);
free(img);
return srv;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment