如何更新附加到精灵的顶点缓冲区或常量缓冲区,以使其在Direct3D 11中在屏幕上平滑移动?

问题描述 投票:0回答:1

我已将纹理附加到一组4个索引顶点的集合上,这些顶点存储在动态顶点缓冲区中。我还向顶点着色器的常量缓冲区添加了转换矩阵。但是,当我尝试更新常量缓冲区以更改转换矩阵以使我可以移动子画面时,子画面无法顺利移动。它会随机停止一小段时间,然后再次移动一小段距离。

下面是渲染功能,主循环和使用的着色器:

    void Sprite::Render(ID3D11DeviceContext* devcon, float dt) {
    // 2D rendering on backbuffer here
    UINT stride = sizeof(VERTEX);
    UINT offset = 0;

    spr_const_data.translateMatrix.r[3].m128_f32[0] += 60.0f*dt;

    devcon->IASetInputLayout(m_data_layout);
    devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    devcon->VSSetShader(m_spr_vert_shader, 0, 0);
    devcon->PSSetShader(m_spr_pixel_shader, 0, 0);

    devcon->VSSetConstantBuffers(0, 1, &m_spr_const_buffer);
    devcon->PSSetSamplers(0, 1, &m_tex_sampler_state);
    devcon->PSSetShaderResources(0, 1, &m_shader_resource_view);

    // select vertex and index buffers
    devcon->IASetIndexBuffer(m_sprite_index_buffer, DXGI_FORMAT_R32_UINT, offset);
    devcon->IASetVertexBuffers(0, 1, &m_sprite_vertex_buffer, &stride, &offset);

    D3D11_MAPPED_SUBRESOURCE ms;
    ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE));
    devcon->Map(m_spr_const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
    memcpy(ms.pData, &spr_const_data, sizeof(spr_const_data));
    devcon->Unmap(m_spr_const_buffer, 0);

    // select which primitive type to use
    // draw vertex buffer to backbuffer
    devcon->DrawIndexed(6, 0, 0);
}

void RenderFrame(float dt) {
        float background_color[] = { 1.0f, 1.0f, 1.0f, 1.0f };

        // clear backbuffer
        devcon->ClearRenderTargetView(backbuffer, background_color);

        knight->Render(devcon, dt);

        // switch back and front buffer
        swapchain->Present(0, 0);
    }

void MainLoop() {
        MSG msg;
        auto tp1 = std::chrono::system_clock::now();
        auto tp2 = std::chrono::system_clock::now();
        while (GetMessage(&msg, nullptr, 0, 0) > 0) {
            tp2 = std::chrono::system_clock::now();
            std::chrono::duration<float> dt = tp2 - tp1;
            tp1 = tp2;
            TranslateMessage(&msg);
            DispatchMessage(&msg);

            RenderFrame(dt.count());
        }
    }
cbuffer CONST_BUFFER_DATA : register(b0)
{
    matrix orthoMatrix;
    matrix translateMatrix;
};

struct VOut {
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
};

VOut VShader(float4 position : POSITION, float2 tex : TEXCOORD0) {
    VOut output;

    position = mul(translateMatrix, position);
    output.position = mul(orthoMatrix, position);
    output.tex = tex;

    return output;
}
Texture2D square_tex;
SamplerState tex_sampler;

float4 PShader(float4 position : SV_POSITION, float2 tex : TEXCOORD0) : SV_TARGET
{
    float4 tex_col = square_tex.Sample(tex_sampler, tex);
    return tex_col;
}

我还包括交换链和后缓冲区的初始化,以防万一由于它而导致的错误。

DXGI_SWAP_CHAIN_DESC scd; // hold swap chain information
        ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

        // fill swap chian description struct
        scd.BufferCount = 1; // one back buffer
        scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
        scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used (draw into back buffer)
        scd.OutputWindow = hWnd; // window to be used
        scd.SampleDesc.Count = 1; // how many multisamples
        scd.Windowed = true; // windowed/full screen

        // create device, device context and swap chain using scd
        D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_DEBUG, nullptr, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, nullptr, &devcon);

        // get address of back buffer
        ID3D11Texture2D* pBackBuffer;
        swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

        // use back buffer address to create render target
        dev->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
        pBackBuffer->Release();

        // set the render target as the backbuffer
        devcon->OMSetRenderTargets(1, &backbuffer, nullptr);

        // Set the viewport
        D3D11_VIEWPORT viewport;
        ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        viewport.Width = WINDOW_WIDTH;
        viewport.Height = WINDOW_HEIGHT;

        devcon->RSSetViewports(1, &viewport); // activates viewport

我还尝试通过D3D11_MAPPED_SUBRESOURCE对象的pData成员获取指向顶点数据的指针,然后将其强制转换为VERTEX*来操作数据,但是问题仍然存在。我想知道如何在窗口上平滑移动精灵。

c++ directx sprite 2d-games direct3d11
1个回答
0
投票

我通过编写固定的FPS游戏循环并将先前状态和当前状态之间的插值提供给render函数来解决此问题。我还以错误的方式更新了常量缓冲区。

© www.soinside.com 2019 - 2024. All rights reserved.