Jump to content

  • Log In with Google      Sign In   
  • Create Account


DirectX11 mip mapping


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
31 replies to this topic

#21 Erik Rufelt   Crossbones+   -  Reputation: 3145

Like
1Likes
Like

Posted 07 September 2012 - 03:30 AM

Providing data for all mip-levels means you explicitly define exactly what each mip-map should contain. This does not make sense together with D3D11_RESOURCE_MISC_GENERATE_MIPS, as the only time you would ever want to generate mips if when you do not have the mip-maps.
I got the impression that this is what you want, for D3D to automatically generate your mipmaps for you.
This is usually done when you actually render data to your texture render-target, and want the mip-maps auto-generated on the GPU after re-rendering the top level.

There is an easier way to do this when loading textures, by calculating the mips on the CPU, and then pass them in with the init-data. I believe D3DX11CreateTextureFromMemory does this automatically for you, if you can use D3DX11.
http://msdn.microsof...7(v=vs.85).aspx

If you do not want to use that function, but do it yourself, there are two ways. You can manually resize your texture to half its size over and over to calculate all the mip-maps, and upload that data to the texture, using either init-data or UpdateSubresource. There is no real difference between init-data and UpdateSubresource if you have a default usage texture, except for that UpdateSubresource lets you update only one particular mip-level (be it the largest or any other).
The other option is to let D3D generate mipmaps with D3D11_RESOURCE_MISC_GENERATE_MIPS.

Using UpdateSubresource you can at any time change a D3D11_USAGE_DEFAULT texture without re-creating the texture.
Is your goal to do this during a game-frame, and automatically have mipmaps generated for your new texture?
Or do you just want to create a texture with mipmaps once that is static until the next time data/levels/other is reloaded?

If you do want the mip-maps auto-generated like that, then create your texture with default usage, mipmap-generation, and 0 as MipLevels, without any initialization data. Then call UpdateSubresource to update mip-level 0 and then call GenerateMips.

UpdateSubresource should be used something like this:
D3D11_BOX box;
box.left = 0;
box.right = width;
box.top = 0;
box.bottom = height;
box.front = 0;
box.back = 1;

deviceContext->UpdateSubresource(
  texture2D, // the texture to update
  0, // first mip-level
  &destBox, // position of the pixels to update in the texture
  pixels.Get(), // image data
  width * 4, // row pitch
  0 // not used for 2D textures
};

Also, I recommend that you visit the documentation-pages at MSDN or in the documentation that comes with the DirectX SDK, and carefully read through all the documentation for the functions you use. It is immensely helpful and will make you a better programmer. Everything we have said is described in detail on the documentation pages. You are not supposed to know everything by heart, but know where to look it up when you need it.

Edited by Erik Rufelt, 07 September 2012 - 03:37 AM.


Sponsor:

#22 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 03:50 AM

Wow big answer there, thanks :) !

"I got the impression that this is what you want, for D3D to automatically generate your mipmaps for you."
- Yep that is exactly what I want.

"I believe D3DX11CreateTextureFromMemory does this automatically for you"
- As I'm doing a Metro application, I can't use this library :/

"The other option is to let D3D generate mipmaps with D3D11_RESOURCE_MISC_GENERATE_MIPS."
- I'll try this one because it's not so different from my base code.

"Is your goal to do this during a game-frame, and automatically have mipmaps generated for your new texture?"
- Yes, as the object get far from the camera I want the mip map to update to a lower resolution texture in the better case

I'll try with the UpdateSubresource method and tell you if all works properly. Thanks again mate :) !

#23 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 04:17 AM

Okay, I made this :
D3D11_BOX destBox;
destBox.left = 0;
destBox.right = width;
destBox.top = 0;
destBox.bottom = height;
destBox.front = 0;
destBox.back = 1;

std::unique_ptr<byte[]> bitmapPixels(new byte[width * height * 4]);
m_d3dDeviceContext->UpdateSubresource(
   this->texture.Get(),  // the texture to update
   0,	   // first mip-level
   &destBox,	 // position of the pixels to update in the texture
   bitmapPixels.get(),   // image data
   width * 4,	 // row pitch
   0	   // not used for 2D textures
);
m_d3dDeviceContext->GenerateMips(this->textureView.Get());

It still does'nt work but gives me another error, I'll try to find what's wrong and tell you how it goes.

Edited by Visje, 07 September 2012 - 06:25 AM.


#24 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 07:01 AM

So I've managed to get it to work, the code compiles and the app launches but none of my textures are displayed :/ instead I get some weird white squares (the colored background should also be textured):

Posted Image

#25 Erik Rufelt   Crossbones+   -  Reputation: 3145

Like
0Likes
Like

Posted 07 September 2012 - 07:12 AM

Copy paste your entire texture init code as it is now, from where you get your image data to where you call GenerateMips, including the structures you have already shown for the texture description, as they appear now.

#26 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 07:23 AM

Ok.

First I create the texture with a call to Basic Loader, then I get the size of the texture + texture & textureView into my class :

BasicLoader^ loader = ref new BasicLoader(m_d3dDevice.Get());
loader->LoadTexture(fileName_, &texture, &textureView);
D3D11_TEXTURE2D_DESC textDesc;
texture->GetDesc(&textDesc);
w = textDesc.Width;
h = textDesc.Height;
contentSize.width = w;
contentSize.height = h;


Inside the BasicLoader, this is what I do (important part only) :

D3D11_TEXTURE2D_DESC textureDesc;	  
ZeroMemory( &textureDesc, sizeof(textureDesc) );
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.MipLevels = 0;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

HRESULT hr = m_d3dDevice->CreateTexture2D(
				&textureDesc,
				NULL,
				&texture2D
				);


And at each frame, I make a call to a function that contains the "updateSubResource" & the GenerateMips:

D3D11_BOX destBox;
destBox.left = 0;
destBox.right = this->contentSize.width;
destBox.top = 0;
destBox.bottom = this->contentSize.height;
destBox.front = 0;
destBox.back = 1;

ComPtr<IWICFormatConverter> formatConverter;
Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
if (m_wicFactory.Get() == nullptr)
		{
			DX::ThrowIfFailed(
				CoCreateInstance(
					CLSID_WICImagingFactory,
					nullptr,
					CLSCTX_INPROC_SERVER,
					IID_PPV_ARGS(&m_wicFactory)
					)
				);
		}
		DX::ThrowIfFailed(
			m_wicFactory->CreateFormatConverter(&formatConverter)
			);
int taille = this->contentSize.width * this->contentSize.height * 4;
std::unique_ptr<byte[]> bitmapPixels(new byte[taille]);

// ************* THE PROGRAM IS CRASHING HERE; IF I DON'T PUT THIS, IT'S NOT CRASHING BUT THE TEXTURES ARE NOT DISPLAYED ! *************
DX::ThrowIfFailed(
			formatConverter->CopyPixels(
				nullptr,
				this->contentSize.width * 4,
				this->contentSize.width * this->contentSize.height * 4,
				bitmapPixels.get()
				)
			);
// *********************************************************************************************************************************************** 

m_d3dDeviceContext->UpdateSubresource(
  this->texture.Get(),  // the texture to update
  0,	   // first mip-level
  &destBox,	 // position of the pixels to update in the texture
  bitmapPixels.get(),   // image data
  this->contentSize.width * 4,	 // row pitch
  0	   // not used for 2D textures
);

m_d3dDeviceContext->GenerateMips(this->textureView.Get());
There's a comment line in CAPITALS for you upward.

Edited by Visje, 07 September 2012 - 07:24 AM.


#27 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 08:12 AM

Yaaay I just got it to work ! :)

The problem is now that it's incredibly laggy... maybe because I do the UpdateSubresource + generateMips each frame... ?

#28 Erik Rufelt   Crossbones+   -  Reputation: 3145

Like
1Likes
Like

Posted 07 September 2012 - 08:26 AM

Nice!
Yes, you probably don't need to do that. You should only update and generate each frame if you load a new texture each frame so you need to reset the texture. Try doing the UpdateSubresource and GenerateMips only at load-time and you should be good to go. Provided ofcourse the texture is static. Animated textures are harder and you would need to optimize instead, preferably by keeping them all on the GPU the whole time.

Edited by Erik Rufelt, 07 September 2012 - 08:27 AM.


#29 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 08:32 AM

The textures are static, I'll try this and hope it won't be so laggy, because it's unplayable right now.

#30 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 08:48 AM

Alright, it works fine ! :D The game is not lagging and the colors and textures are alright with a mipLevel of 0.
Thank you so much Erik !!

The only thing remaining is that it's still lagging a bit on the menu where I wanted the mip mapping applied; do I have to call a particular function like GenerateMips on frameTime or I can't do anything about it ?

#31 Erik Rufelt   Crossbones+   -  Reputation: 3145

Like
0Likes
Like

Posted 07 September 2012 - 09:15 AM

You should be able to call GenerateMips only once at load time also, right after UpdateSubresource, and during frame-time use the exact same code as before when mip-levels was 1.

#32 Visje   Members   -  Reputation: 109

Like
0Likes
Like

Posted 07 September 2012 - 09:19 AM

I'll do that. Thanks




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS