Sign in to follow this  
-Tau-

Texture array with mipmaps

Recommended Posts

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?

Share this post


Link to post
Share on other sites

Why does a 256x256 px texture have 9 mip levels, and how do i get number of mip levels from a texture?

 

A mip halves in size (w & h) each time: 256px, 128, 64, 32, 16, 8, 4, 2, 1 = 9 mips (or the original image and 8 mips :P)

https://en.wikipedia.org/wiki/Mipmap#How_it_works

 

public static int CountMipMaps(int width, int height)
{
  int m = Math.Max(width, height);

  int i = 0;
  while (m > 0)
  {
    m >>= 1;
    i++;
  }

  return i;
}

Share this post


Link to post
Share on other sites

Solved with

pDeviceContext->CopySubresourceRegion(pTextureArray, i * 9, 0, 0, 0, pNewTexture, 0, 0);

pDeviceContext->GenerateMips(pTextureSRV);

Edited by -Tau-

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this