Sign in to follow this  

Texture array with mipmaps

This topic is 472 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

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

This topic is 472 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.

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