Я прикрепил текстуру к набору из 4 проиндексированных вершин, которые хранятся в динамическом буфере вершин c. Я также добавил матрицу перевода в постоянный буфер вершинного шейдера. Однако, когда я пытаюсь обновить постоянный буфер, чтобы изменить матрицу перевода, чтобы я мог переместить спрайт, спрайт не перемещается плавно. Он останавливается случайным образом на короткое время, прежде чем снова перемещаться на небольшое расстояние.
Ниже приведены функции рендеринга, основные l oop и используемые шейдеры:
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;
}
Я также включил инициализацию swapchain и backbuffer на случай, если из-за этого произошла ошибка.
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
Я также попытался получить указатель на данные вершин через член pData объект D3D11_MAPPED_SUBRESOURCE и затем преобразует его в VERTEX*
для манипулирования данными, но проблема остается. Я хотел бы знать, как плавно перемещать спрайт по окну.