Jump to content
  • Advertisement
Sign in to follow this  
-Tau-

Texture array with mipmaps

This topic is 686 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
Advertisement

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
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!