locked
Update a texture at runtime?

    Question

  • Hello people,

    At the moment I am attempting to update a texture on a cube at runtime. I loaded the textures in using the DDSTextureLoader that came with the DirectX Tool Kit.

    To be more specific I have an array of cubes which are allocated textures and it is easy enough to load the different textures on the initial render but I can not seem to change say any set value of the array to another value at run time on even a key press. 

    Monday, January 28, 2013 2:12 PM

All replies

  • In DirectX 11, there is a call to Create and Input Layout, that is bound to 1 shader, (Vertex, Geometry, Pixel, whatever). 

    When you create an Input Element Description for the given cube, you specify parameters that you are passing into the shader with different semantics: "POSITION", "TEXCOORD", etc.

    Based on the signature of the vertex data in the buffer, the correct shader will be invoked.

    In other words, if you have not created another input layout, with the new texture on it, updated the old one, replaced the old one, etc, nothing will change that is being rendered because the texture has been cached, and the cached copy is being used.

    HTH


    • Edited by e kohen Monday, January 28, 2013 4:56 PM Fixed Type-o
    • Proposed as answer by e kohen Monday, January 28, 2013 4:56 PM
    Monday, January 28, 2013 4:55 PM
  • Actually that's not correct. There are some potential timing issues of when the GPU will make use of the texture that require some awareness of synchronization, but this usually results in 'stalls' on the GPU rather than 'incorrect' results.

    To the original poster:

    DDSTextureLoader (in both the DirectXTK and the standalone version in the DirectXTex package) now have TWO versions of the function. The 'simple' one, :CreateDDSTextureFromFile, assumes a usage=D3D11_USAGE_DEFAULT, bindFlags=D3D11_BIND_SHADER_RESOURCE, cpuAccessFlags=0, miscFlags=0.

    This default can be updated via UpdateSubresource, but not by Map/Unmap.

    There is an 'advanced' version CreateDDSTextureFromFileEx where you could use a different usage such as D3D11_USAGE_DYNAMIC with a different cpuAccessFlags to support Map style updating (for very frequently updated textures) or even D3D11_USAGE_IMMUTABLE for textures that never change after being created.

    Monday, January 28, 2013 7:58 PM
  • Note that you cannot use mipmapping with D3D11_USAGE_DYNAMIC.
    Monday, January 28, 2013 9:48 PM
  • Sorry to be a nuisance but this has been troubling me for weeks now. I am using UpdateSubresources but obviously not in the correct way. I can change the scale,rotation and translation of the entire rendered level but no joy with changing the texture at runtime.

    In my Level class I load in the different textures like so:

    Level::Level(Microsoft::WRL::ComPtr<ID3D11Device1> dev, Microsoft::WRL::ComPtr<ID3D11DeviceContext1> devCon) { texture1 = texture2 = nullptr; CreateDDSTextureFromFile(aDev.Get(), L"Assets\\Textures\\earth.dds",NULL, texture1.GetAddressOf()) ;//create earth texture CreateDDSTextureFromFile(aDev.Get(), L"Assets\\Textures\\rock.dds",NULL, texture2.GetAddressOf()) ;//create rock texture createLevel(dev, devCon); }


    Within createLevel I initialize the array and assign graphics elements to it. One thing I have found is if I try to update the

    texture after the graphics elements are assigned nothing happens. However if I try to update the texture before the graphic elements

    are assigned then it automatically renders that texture even without a key press.

    In my Game class UpdateResource is called in the Update function like so:

    void Game::Update(float timeTotal, float timeDelta)
    {
       d3dContext->UpdateSubresource(
    		constantBuffer[0].Get(),
    		0,
    		NULL,
    		&constantBufferData,
    		0,
    		0
    		);
    }

    Thanks for the help so far.







    • Edited by Graeme_Burr Tuesday, January 29, 2013 12:43 PM typo
    Tuesday, January 29, 2013 5:50 AM
  • Level::Level(Microsoft::WRL::ComPtr<ID3D11Device1> dev, Microsoft::WRL::ComPtr<ID3D11DeviceContext1> devCon)

    In C++, this doesn't do what you think it does. It's making a COPY of the smart pointer when you call and making a new one that is deleted on exit from the function.

    When passing smartpointers, you should either

    (A) pass raw pointers

     

    Level::Level(ID3D11Device1* dev, ID3D11DeviceContext1* devCon)
    
    ...
    
    new Level( dev.Get(), devcon.Get() );

    or

    (B) pass a reference to the smart pointer

     
    Level::Level(Microsoft::WRL::ComPtr<ID3D11Device1>& dev, Microsoft::WRL::ComPtr<ID3D11DeviceContext1>& devCon)

     


    Tuesday, January 29, 2013 7:59 PM
  • Instead of doing

    texture1 = texture2 = nullptr;
    	
    CreateDDSTextureFromFile(aDev.Get(), L"Assets\\Textures\\earth.dds",NULL, texture1.GetAddressOf()) ;//create earth texture
    CreateDDSTextureFromFile(aDev.Get(), L"Assets\\Textures\\rock.dds",NULL, texture2.GetAddressOf()) ;//create rock texture
    

    you should use ReleaseAndGetAddressOf

    CreateDDSTextureFromFile(aDev.Get(), L"Assets\\Textures\\earth.dds",NULL, texture1.ReleaseAndGetAddressOf()) ;//create earth texture
    CreateDDSTextureFromFile(aDev.Get(), L"Assets\\Textures\\rock.dds",NULL, texture2.ReleaseAndGetAddressOf()) ;//create rock texture
    

    Tuesday, January 29, 2013 8:01 PM
  • I don't really understand your usage here. Generally if you want to switch textures "on-the-fly' you'd just load both textures at once and use a different one at render time.
    Tuesday, January 29, 2013 8:04 PM
  • What I'm trying to do is procedurally generate a 3D dungeon  made of cubes with use of a 2D array; segment by segment on completion sort of way. To get the array values to visually represent change is my problem. Didn't want to say that in the first post as not to scare away potential help. Hard coding the array works fine and all the different textures used appear as they should and have the correct functionality such as path, wall etc. 

    Just need to get the array value to change visually. You have helped a lot so far and I thank you for that. The array updates to the extent that if I change a value of the array from say wall to path the player will be able to walk on the block which has been changed or vice versa. 

    The Render method in the Game class looks like this at the moment:

    void Level::Render(Microsoft::WRL::ComPtr<ID3D11DeviceContext1>& devCon, Microsoft::WRL::ComPtr<ID3D11Buffer>& constBuff)
    {
    
    	for (unsigned int i = 0; i < dungeonElements.size(); i++)
    		for (unsigned int j = 0; j < dungeonElements[i].size(); j++)
    		{
    				dungeonElements[i][j]->Render(devCon, constBuff);					
    		}
    
    dungeonArray[12][10] = 2; // test changing element which contains the different textures etc at render time (2 = earth Texture).
    								
    }
    

    The block that was a a rock value gets the physical properties of earth such as being able to walk on and such but the texture remains the same. Meaning the player can now walk through the once unpassable rock block but it still looks the same. Any ideas?

    Wednesday, January 30, 2013 3:22 AM