(DirectX 11)具有恒定场景内容更改的动态顶点/索引缓冲区实现 [英] (DirectX 11) Dynamic Vertex/Index Buffers implementation with constant scene content changes

查看:68
本文介绍了(DirectX 11)具有恒定场景内容更改的动态顶点/索引缓冲区实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

曾经(与我同在)第一次钻研非托管DirectX 11,但有一个问题,尽管在论坛上被问了几次,仍然给我带来了疑问.

Been delving into un-managed DirectX 11 for the first time (bear with me) and there's an issue that, although asked several times over the forums still leaves me with questions.

我正在开发一个应用程序,其中随着时间的推移将对象添加到场景中.在每个渲染循环中,我都希望收集场景中的所有顶点,并将其重新使用单个顶点和索引缓冲区,以实现性能和最佳实践.我的问题是关于动态顶点和索引缓冲区的用法.当场景内容更改时,我还无法完全理解它们的正确用法.

I am developing as app in which objects are added to the scene over time. On each render loop I want to collect all vertices in the scene and render them reusing a single vertex and index buffer for performance and best practice. My question is regarding the usage of dynamic vertex and index buffers. I haven't been able to fully understand their correct usage when scene content changes.

vertexBufferDescription.Usage               = D3D11_USAGE_DYNAMIC;
vertexBufferDescription.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDescription.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
vertexBufferDescription.MiscFlags           = 0;
vertexBufferDescription.StructureByteStride = 0;

在场景初始化时是否应该创建缓冲区,并以某种方式在每个帧中更新它们的内容?如果是这样,我应该在缓冲区描述中设置什么ByteSize?而我用它初始化什么呢?

Should I create the buffers when the scene is initialized and somehow update their content in every frame? If so, what ByteSize should I set in the buffer description? And what do I initialize it with?

或者,我是否应该使用当前顶点数作为其大小在第一次渲染场景(帧1)时创建它?如果是这样,当我向场景中添加另一个对象时,是否不需要重新创建缓冲区并将缓冲区描述的ByteWidth更改为新的顶点数?如果我的场景在每一帧上都不断更新其顶点,则使用单个动态缓冲区将以这种方式失去其目的...

Or, should I create it the first time the scene is rendered (frame 1) using the current vertex count as its size? If so, when I add another object to the scene, don't I need to recreate the buffer and changing the buffer description's ByteWidth to the new vertex count? If my scene keeps updating its vertices on each frame, the usage of a single dynamic buffer would loose its purpose this way...

我一直在尝试在场景第一次渲染时初始化缓冲区,并从那时开始,在每个帧上使用Map/Unmap.我首先用所有场景对象填充向量列表,然后像这样更新资源:

I've been testing initializing the buffer on the first time the scene is rendered, and from there on, using Map/Unmap on each frame. I start by filling in a vector list with all the scene objects and then update the resource like so:

void Scene::Render() 
{
    (...)

    std::vector<VERTEX> totalVertices;
    std::vector<int> totalIndices;
    int totalVertexCount = 0;
    int totalIndexCount = 0;

    for (shapeIterator = models.begin(); shapeIterator != models.end(); ++shapeIterator)
    {
            Model* currentModel = (*shapeIterator);

            // totalVertices gets filled here...
    }

     // At this point totalVertices and totalIndices have all scene data

    if (isVertexBufferSet)
    {
        // This is where it copies the new vertices to the buffer.
        // but it's causing flickering in the entire screen...
        D3D11_MAPPED_SUBRESOURCE resource;
        context->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
        memcpy(resource.pData, &totalVertices[0], sizeof(totalVertices));
        context->Unmap(vertexBuffer, 0);
    }
    else
    {
        // This is run in the first frame. But what if new vertices are added to the scene?
        vertexBufferDescription.ByteWidth = sizeof(VERTEX) * totalVertexCount;
        UINT stride = sizeof(VERTEX);
        UINT offset = 0;

        D3D11_SUBRESOURCE_DATA resourceData;
        ZeroMemory(&resourceData, sizeof(resourceData));
        resourceData.pSysMem = &totalVertices[0];

        device->CreateBuffer(&vertexBufferDescription, &resourceData, &vertexBuffer);
        context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
        isVertexBufferSet = true;
    }

在渲染循环的最后,在跟踪每个对象的顶点的缓冲区位置的同时,我最终调用Draw():

In the end of the render loop, while keeping track of the buffer position of the vertices for each object, I finally invoke Draw():

    context->Draw(objectVertexCount, currentVertexOffset);
}

我当前的实现导致整个场景闪烁.但是没有内存泄漏.想知道它是否与我使用Map/Unmap API的方式有关?

My current implementation is causing my whole scene to flicker. But no memory leaks. Wonder if it has anything to do with the way I am using the Map/Unmap API?

此外,在这种情况下,什么时候调用buffer-> Release()是理想的选择?提示或代码示例将非常棒!预先感谢!

Also, in this scenario, when would it be ideal to invoke buffer->Release()? Tips or code sample would be great! Thanks in advance!

推荐答案

在进入顶点缓冲区的memcpy中,请执行以下操作:

At the memcpy into the vertex buffer you do the following:

memcpy(resource.pData, &totalVertices[0], sizeof(totalVertices));

sizeof(totalVertices)只是要求std :: vector<的大小.VERTEX>这不是您想要的.

sizeof( totalVertices ) is just asking for the size of a std::vector< VERTEX > which is not what you want.

尝试以下代码:

memcpy(resource.pData, &totalVertices[0], sizeof( VERTEX ) * totalVertices.size() );

当isVertexBufferSet为true时,您似乎没有调用 IASetVertexBuffers .确保您这样做.

Also you don't appear to calling IASetVertexBuffers when isVertexBufferSet is true. Make sure you do so.

这篇关于(DirectX 11)具有恒定场景内容更改的动态顶点/索引缓冲区实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆