Search code examples
c++arrayspointersdirectxvertex

Diectx11 Pointing to vertex buffer from another function/ Trying to use multiple textures


Edit/ Update: Put in my most recent code, and asking a new question about texturing if you still have time to help me.

Original problem: I need to have the vertex buffer in its own function, I'm trying to make it with variables for vertices so I can run an array of randomly generated co-ordinates through it and result in many instances of cubes which I can control the size of.

Your advice set me on the right track and I was able to make the vertex buffer work in a separate function as desired. I may have set myself up for problems later on so I'm trying to show as much relevant code as possible just in case.

New problem: My next step is to do what I just did but drawing a different set of cubes (Friendlies, so different size, which is why I wanted to make the buffer more dynamic so I can re-use it for everything). I think I can manage that part fine, but first I need to figure out how to run multiple textures so I can tell which is which (Also because onscreen text will be done by texturing squares with pictures of letter/ numbers.)

Here is the code involved:

struct VERTEX {FLOAT X, Y, Z; D3DXVECTOR3 Normal; FLOAT U, V;};

void InitGraphics()
{
// create the vertex buffer
D3D11_BUFFER_DESC bd;
D3D11_MAPPED_SUBRESOURCE ms;

ZeroMemory(&bd, sizeof(bd));    

bd.Usage = D3D11_USAGE_DYNAMIC; 
bd.ByteWidth = sizeof(VERTEX) * 24; // size is the VERTEX struct * amount of vertices stored
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;    
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 

dev->CreateBuffer(&bd, NULL, &pVBuffer);    // create the buffer

// create the index buffer out of DWORDs
DWORD IndexList[] = 
{
    0,1,2,3,                        
    4,5,6,7,                        
    8,9,10,11,                      
    12,13,14,15,
    16,17,18,19,
    20,21,22,23,
};

// create the index buffer
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(DWORD) * 24;  // Changed to match the amount of indices used
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;

dev->CreateBuffer(&bd, NULL, &pIBuffer);

devcon->Map(pIBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
memcpy(ms.pData, IndexList, sizeof(IndexList));         
devcon->Unmap(pIBuffer, NULL);          


D3DX11CreateShaderResourceViewFromFile
(dev,           // the Direct3D device
L"Wood.png",        // load Wood.png in the local folder
NULL,           // no additional information
NULL,           // no multithreading
&pTexture,      // address of the shader-resource-view
NULL);          // no multithreading

}

void RenderFrame(void)
{
    ...
    devcon->UpdateSubresource(pCBuffer, 0, 0, &cBuffer, 0, 0);
    devcon->PSSetShaderResources(0, 1, &pTexture);
    ...
    DrawStuff();
}

I was able to follow your directions and bring the memcpy line into the other function as seen below but had to bring a couple other lines along with it to make it work. I included more of the code this time to show what else is in the InitGraphics function as my next problem is trying to figure out how to use multiple textures.

The vertex buffer now looks like this:

void VertBuffer()
{
    VERTEX VertList[] =
    {
        {(vVX - vS + 0.0f), (- vS + 0.0f), (vVZ - vS + 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), 0.0f, 0.0f},
        {(vVX - vS + 0.0f), (vS + 0.0f), (vVZ - vS + 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), 0.0f, 1.0f},
        {(vVX + vS + 0.0f), (- vS + 0.0f), (vVZ - vS + 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), 1.0f, 0.0f},
        {(vVX + vS + 0.0f), (vS + 0.0f), (vVZ - vS + 0.0f), D3DXVECTOR3(0.0f, 0.0f, -1.0f), 1.0f, 1.0f},            // side 1

        ...
    }; 

        D3D11_MAPPED_SUBRESOURCE ms;

            devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);        
            memcpy(ms.pData, VertList, sizeof(VertList));                               
            devcon->Unmap(pVBuffer, NULL);  
}

This is where vVX and vVZ are co-ordinates randomly generated and stored in an array and then vS is to manipulate the size of the cube. When I last posted I was still having problems with it because I managed to get the vertex buffer working in its own function, but I could still only call it once at the beginning which meant none of the variables took place. I tried putting it in DrawStuff() but that caused the program to crash after 3-6 seconds. Since then, I have absolutely no idea what I changed or edited but somehow the problem became fixed so now I have a working draw function which looks like this and calls the vertex buffer in every cycle to constantly update it on the locations of the cubes.

void DrawStuff()
{   
    for (j = 0; j < 10; j++)        // Draw 10 Creeps
    {
        for (int i = 0; i < 6; i++)
        {
            vS = 2;                 // Creep size

            vVX = aCMgr [j][0];
            vVZ = aCMgr [j][1];

            VertBuffer();

            devcon->DrawIndexed(4, i * 4, 0);

        }
    }
}

So that seems to be working great now and I'm just going to make multiple of these. One for bad cubes (Creeps), one for the player + friendly cube, and one for lots of squares which will be textured to make up a rudimentary GUI.

After 12 hours of Google searching and re-reading the tutorial website as well as my own code, I've got as far as learning that I need to change the array size in D3D11_TEXTURE2D_DESC and then run the part in InitGraphics multiple times to load up each texture but I still cannot for the life of me figure out at what point to control applying different textures to different objects.

Here's (I think) all the code I have relating to textures:

ID3D11ShaderResourceView *pTexture;         // The pointer to the texture shader

void InitD3D(HWND hWnd)
{
...
D3D11_TEXTURE2D_DESC texd;
    ZeroMemory(&texd, sizeof(texd));

    texd.Width = 512;
    texd.Height = 512;
    texd.ArraySize = 3;
    texd.MipLevels = 1;
    texd.SampleDesc.Count = 4;
    texd.Format = DXGI_FORMAT_D32_FLOAT;
    texd.BindFlags = D3D11_BIND_DEPTH_STENCIL;

    ID3D11Texture2D *pDepthBuffer;
    dev->CreateTexture2D(&texd, NULL, &pDepthBuffer);
...
}

I changed ArraySize to 3, assuming I will have 3 different images which will be used to texture everything. From my understanding, I need to run D3DX11CreateShaderResourceViewFromFile three times, once for each texture? Where would I go from here?


Solution

  • You can put the Vertex array and memcpy together in a same function and call this function in InitGraphics().

    void InitVertexBuffer()
    {
        VERTEX VertList[] =
        {
            {-1.0f, -1.0f, -1.0f, D3DXVECTOR3(0.0f, 0.0f, -1.0f), 0.0f, 0.0f},          
            {-1.0f, 1.0f, -1.0f, D3DXVECTOR3(0.0f, 0.0f, -1.0f), 0.0f, 1.0f},
            {1.0f, -1.0f, -1.0f, D3DXVECTOR3(0.0f, 0.0f, -1.0f), 1.0f, 0.0f},
            {1.0f, 1.0f, -1.0f, D3DXVECTOR3(0.0f, 0.0f, -1.0f), 1.0f, 1.0f},
        }; 
    
        // Some code else....
    
        memcpy(ms.pData, VertList, sizeof(Vertlist));
    }
    
    
    void InitGraphics() 
    {
        // ... Code to initialized D3D11
    
        InitVertexBuffer();
    }
    

    Another thing I want to point is in DirectX11, you don't necessary need to use memcpy, you can bind the vertex data before creating vertex buffer, as below.

    // The vertex format
    struct SimpleVertex
    {
        DirectX::XMFLOAT3 Pos;  // Position
        DirectX::XMFLOAT3 Color; // color
    };
    
    
    VOID InitVertexBuffer()
    {
    
        // Create the vertex buffer
        SimpleVertex vertices[] = 
        {
            { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT3( 0.0f, 0.0f, 1.0f) },
            { XMFLOAT3( 1.0f,  1.0f, -1.0f ), XMFLOAT3( 0.0f, 1.0f, 0.0f) },
            { XMFLOAT3( 1.0f,  1.0f,  1.0f ), XMFLOAT3( 0.0f, 1.0f, 1.0f) },
            { XMFLOAT3(-1.0f,  1.0f,  1.0f ), XMFLOAT3( 1.0f, 0.0f, 0.0f) },
            { XMFLOAT3(-1.0f, -1.0f, -1.0f ), XMFLOAT3( 1.0f, 0.0f, 1.0f) },
            { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT3( 1.0f, 1.0f, 0.0f) },
            { XMFLOAT3( 1.0f, -1.0f,  1.0f ), XMFLOAT3( 1.0f, 1.0f, 1.0f) },
            { XMFLOAT3(-1.0f, -1.0f,  1.0f ), XMFLOAT3( 0.0f, 0.0f, 0.0f) },
        };
    
        // Vertex Buffer
        D3D11_BUFFER_DESC bd;
        ZeroMemory(&bd, sizeof(bd));
        bd.Usage = D3D11_USAGE_DEFAULT;
        bd.ByteWidth = sizeof(vertices);
        bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
        bd.CPUAccessFlags = 0;
    
        // copy vertex buffer data
        D3D11_SUBRESOURCE_DATA initData;
        ZeroMemory(&initData, sizeof(initData));
        initData.pSysMem = vertices; ////////////////// Bind your vertex data here.
        HRESULT hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBuffer);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Create vertex buffer failed", L"Error", 0);
        }
    }