Hello, a while ago i started to use texture arrays for multitexturing in terrain shader. I didn't know how to load image files for texture array, so i used ID3D11DeviceContext::CopySubresourceRegion to populate texture array with textures loaded with WICTextureLoader.
That looks like this:
D3D11_TEXTURE2D_DESC textureDesc; D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc; ZeroMemory(&shaderResourceViewDesc, sizeof(shaderResourceViewDesc)); ZeroMemory(&textureDesc, sizeof(textureDesc)); textureDesc.Width = TEX_PIXEL_SIZE; textureDesc.Height = TEX_PIXEL_SIZE; textureDesc.MipLevels = 1; textureDesc.ArraySize = v_texFName.size() + 1; textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; textureDesc.SampleDesc.Count = 1; textureDesc.Usage = D3D11_USAGE_DEFAULT; textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = 0; shaderResourceViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; shaderResourceViewDesc.Texture2DArray.MostDetailedMip = 0; shaderResourceViewDesc.Texture2DArray.MipLevels = 1; shaderResourceViewDesc.Texture2DArray.ArraySize = v_texFName.size() + 1; shaderResourceViewDesc.Texture2DArray.FirstArraySlice = 0; HRESULT hr; hr = pd3dDevice->CreateTexture2D(&textureDesc, 0, &pTextureArray); if (FAILED(hr)) debugMsg("FAIL pTextureArray: %d", hr); hr = pd3dDevice->CreateShaderResourceView(pTextureArray, &shaderResourceViewDesc, &pTextureSRV); if (FAILED(hr)) debugMsg("FAIL pTextureSRV: %d", hr); WCHAR wcharstr[260]; ID3D11Resource *pNewTexture; for (UINT i = 0; i < v_texFName.size(); i++) { MultiByteToWideChar(CP_ACP, 0, v_texFName[i]->text, -1, wcharstr, 260); CreateWICTextureFromFile(pd3dDevice, wcharstr, &pNewTexture, 0); DXUTGetD3D11DeviceContext()->CopySubresourceRegion(pTextureArray, i, 0, 0, 0, pNewTexture, 0, 0); SAFE_RELEASE(pNewTexture); }
Now after reading some articles i noticed that WICTextureLoader can automatically generate mipmaps.
CreateWICTextureFromFileEx(pd3dDevice, pDeviceContext, wcharstr, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, 0, D3D11_RESOURCE_MISC_GENERATE_MIPS, false, &pNewTexture, 0);
But now i don't know how to copy these mipmapped textures into texture array.
According to some articles it should work like this:
textureDesc.MipLevels = 0; textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; shaderResourceViewDesc.Texture2DArray.MipLevels = -1; // if texture has 9 mipmap levels for (UINT i = 0; i < v_texFName.size(); i++) { MultiByteToWideChar(CP_ACP, 0, v_texFName[i]->text, -1, wcharstr, 260); CreateWICTextureFromFileEx(pd3dDevice, DXUTGetD3D11DeviceContext(), wcharstr, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, 0, D3D11_RESOURCE_MISC_GENERATE_MIPS, false, &pNewTexture, 0); for (UINT j = 0; j < 9; j++) DXUTGetD3D11DeviceContext()->CopySubresourceRegion(pTextureArray, i * 9 + j, 0, 0, 0, pNewTexture, j, 0); SAFE_RELEASE(pNewTexture); }
But this doesn't seem to work. (it works only for the nearest mip level)
My questions are:
Why does a 256x256 px texture have 9 mip levels, and how do i get number of mip levels from a texture?
Why does the last code work only for the first mip level?
How do i populate a texture array with mipmapped textures?