Jump to content
  • Advertisement
Sign in to follow this  
ErnstH

Generate mipmaps for DDS cubemaps in DirectX 11

This topic is 1472 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm loading my DDS cubemaps with this function:

 

HRESULT hr = CreateDDSTextureFromFile(mDevice, inPath, &Texture, &mShaderResourceView);

 

This works fine, except it has no mipmaps.

According to this page:

https://directxtk.codeplex.com/wikipage?title=DDSTextureLoader

I have to use the Ex version:

 

unsigned int bindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
unsigned int miscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

HRESULT hr=CreateDDSTextureFromFileEx(mDevice, mContext, inPath, 0, D3D11_USAGE_DEFAULT, bindFlags, 0, miscFlags, false, &Texture, &mShaderResourceView);

 

However, no matter what I try I get a:

E_INVALIDARG One or more arguments are invalid

 

When stepping through the code I found out that the format is DXGI_FORMAT_BC1_UNORM (71) and this format is not supported for auto-gen mipmaps for my feature level and it finally fails at the CreateD3DResources function.

 

DirectX 9 has no problems generating mipmaps for this very same DDS file. Does this mean I have to convert the DDS file to another format, like uncompressed? Or is there a way to make it work in DirectX 11?

 

Any hints will be much appreciated!

Share this post


Link to post
Share on other sites
Advertisement

I understand that this is the idea of DDS files.

 

We however need this functionality to stay compatible with the DirectX 9 version of our software.

 

Our users are expecting their projects (with their own DDS files) to render better in a DirectX 11 version. Not worse.

Share this post


Link to post
Share on other sites
For what I can see it is failing because what DX9 did was to decompress, generate mips, compress again. Which is a lossy operation (theoretically it can be done as a lossless conversion by replacing binary data of mip 0 of the recompressed stream with the one from the original bc1, however the generated mips from bc1 sources should be of lower quality than generating mips from original sources).

Most likely D3D11 forces you to greater quality by first generating the mips from the source material, then compress. If the dds is already compressed and you want to pay the price, decompress it first. Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

Thank you for the info.

 

I think I'try the latter option first. I'll let you know how it goes.

Share this post


Link to post
Share on other sites
I managed to add mipmapping to the BC1 encoded DDS cubemaps. Here's what I do:
 
1) Create a texture using the CreateDDSTextureFromFile function
 
ID3D11Resource* Texture = nullptr;
 
HRESULT hr = CreateDDSTextureFromFile(mDevice, inPath, &Texture, &mShaderResourceView);
 
2) Get the resolution
 
D3D11_TEXTURE2D_DESC d;
ZeroMemory(&d, sizeof(d));
 
Texture->GetDesc(&d);
mWidth = d.Width;
mHeight = d.Height;
 
3) Create a new cubemap texture with the same resolution
 
mFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
 
D3D11_TEXTURE2D_DESC d;
ZeroMemory(&d, sizeof(d));
 
d.Width = mWidth;
d.Height = mHeight;
d.MipLevels = 0;
d.ArraySize = 6;
d.Format = mFormat;
d.SampleDesc.Count = 1;
d.SampleDesc.Quality = 0;
d.Usage = D3D11_USAGE_DEFAULT;
d.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
d.CPUAccessFlags = 0;
d.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | D3D11_RESOURCE_MISC_GENERATE_MIPS;
 
HRESULT hr = mDevice->GetDevice()->CreateTexture2D(&d, nullptr, &mTexture);
 
4) Create a shader resource view
 
D3D11_SHADER_RESOURCE_VIEW_DESC d;
ZeroMemory(&d, sizeof(d));
 
d.Format = mFormat;
d.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE
d.Texture2D.MipLevels = -1;
 
HRESULT hr = mDevice->CreateShaderResourceView(mTexture, &d, &mShaderResourceView);
 
5) For all 6 faces: create a render target
 
D3D11_RENDER_TARGET_VIEW_DESC d;
ZeroMemory(&d, sizeof(d));
 
d.Format = mFormat;
d.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
d.Texture2DArray.ArraySize = 1;
d.Texture2DArray.FirstArraySlice = inFace;
 
HRESULT hr = mDevice->CreateRenderTargetView(mTexture, &d, &mRenderTargetView);
 
6) For all 6 faces: select this render target:
 
mContext->OMSetRenderTargets(1, &mRenderTargetView, nullptr);
 
7) For all 6 faces, I use my framework to render a square on this render target using the ShaderResourceView created in step 1
 
When your square mesh has UV coordinates ranging from (0,0) top left to (1,1) bottom right, the pixel shader looks something like this:
 
float4 PS(VS_OUTPUT input): SV_Target{
 
    float4 c=float4(1,0,0,1);
 
    if(TextureResolution[0].x>0){
 
        float2 uv=input.tex;
 
        float3 v=float3(0,0,0);
 
        int f=round(Prop[0].x);
 
        if(f==0){
            //+X
            v.x=1;
            v.y=1-uv.y*2;
            v.z=1-uv.x*2;
        }
        else if(f==1){
            //-X
            v.x=-1;
            v.y=1-uv.y*2;
            v.z=-1+uv.x*2;
        }
        else if(f==2){
            //+Y
            v.x=-1+uv.x*2;
            v.y=1;
            v.z=-1+uv.y*2;
        }
        else if(f==3){
            //-Y
            v.x=-1+uv.x*2;
            v.y=-1;
            v.z=1-uv.y*2;
        }
        else if(f==4){
            //+Z
            v.x=-1+uv.x*2;
            v.y=1-uv.y*2;
            v.z=1;
        }
        else if(f==5){
            //-Z
            v.x=1-uv.x*2;
            v.y=1-uv.y*2;
            v.z=-1;
        }
        c=MyTexture0.Sample(MySampler0,normalize(v));
    }
    return c;
}
 
8) After rendering all 6 faces, create the mipmaps
 
mDevice->GenerateMips(mShaderResourceView);
 
That's it. Thanks to MJP for pointing me to the right direction!
Edited by MJP

Share this post


Link to post
Share on other sites

Thank you for sharing your solution! I'm sure that somebody else will find it useful.

I hope you don't mind, but I edited your post to add "code" tags in order to give the code better formatting.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!