Direct3D11 отображает только строки и в странном порядке.

Я уменьшил предыдущую проблему разрыва до ядра, в котором я застрял.

У меня есть буфер вершин, состоящий из 4 вершин, расположенных в плоскости (обозначенных от 0 до 3):

1.  .2

0.  .3

и соответствующий индексный буфер {0,1,2,3,0}.

Теперь, когда я визуализирую с помощью D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, я получаю ожидаемое изображение:

  __ 
 |  |
 |__|

Однако, когда я визуализирую с помощью D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, результат такой:

 | /|
 |/ |

Обратите внимание, что заполнение треугольников не выполняется.

Еще больше сбивает с толку то, что при использовании D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST результат такой:

 |
 |

Если я изменю индексный буфер на {0,1,2,0,2,3}, он отобразит:

 | /
 |/

То есть рисуется всего одна пиксельная линия между первыми двумя вершинами.

Я сократил свои шейдеры до самых примитивных примеров:

Вершинный шейдер:

struct VertexInputType
{
    float4 position : POSITION;
};
struct PixelInputType
{
    float4 position : SV_POSITION;
};
PixelInputType VertexShader(VertexInputType input)
{
    PixelInputType output;
    input.position.w = 1.0f;
    output.position = input.position;
    return output;
}

Пиксельный шейдер:

struct PixelInputType
{
    float4 position : SV_POSITION;
};
float4 PixelShader(PixelInputType input) : SV_TARGET
{
    float4 color;
    color.r = 0;
    color.g = 0;
    color.b = 0;
    color.a = 1;
    return color;
}

В качестве вершин я использую DirectX::XMFLOAT3:

D3D11_INPUT_ELEMENT_DESC polygon_layout[1];
polygon_layout[0].SemanticName = "POSITION";
polygon_layout[0].SemanticIndex = 0;
polygon_layout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygon_layout[0].InputSlot = 0;
polygon_layout[0].AlignedByteOffset = 0;
polygon_layout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygon_layout[0].InstanceDataStepRate = 0;
d3d11_device->CreateInputLayout(polygon_layout, 1, compiled_vshader_buffer->GetBufferPointer(), compiled_vshader_buffer->GetBufferSize(), &input_layout);


D3D11_BUFFER_DESC vertex_buffer_desc;
vertex_buffer_desc.Usage = D3D11_USAGE_DEFAULT;
vertex_buffer_desc.ByteWidth = sizeof(DirectX::XMFLOAT3) * 4;
vertex_buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertex_buffer_desc.CPUAccessFlags = 0;
vertex_buffer_desc.MiscFlags = 0;
vertex_buffer_desc.StructureByteStride = 0;
DirectX::XMFLOAT3 vertices[4];
vertices[0].x = -0.5;    vertices[0].y = -0.5;    vertices[0].z = 0;
vertices[1].x = -0.5;    vertices[1].y =  0.5;    vertices[1].z = 0;
vertices[2].x =  0.5;    vertices[2].y =  0.5;    vertices[2].z = 0;
vertices[3].x =  0.5;    vertices[3].y = -0.5;    vertices[3].z = 0; 
D3D11_SUBRESOURCE_DATA vertex_buffer_data;
vertex_buffer_data.pSysMem = vertices;
vertex_buffer_data.SysMemPitch = 0;
vertex_buffer_data.SysMemSlicePitch = 0;
hr = d3d11_device->CreateBuffer(&vertex_buffer_desc, &vertex_buffer_data, &vertex_buffer);

D3D11_BUFFER_DESC index_buffer_desc;
index_buffer_desc.Usage = D3D11_USAGE_DEFAULT;
index_buffer_desc.ByteWidth = sizeof(int32_t) *  6;
index_buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
index_buffer_desc.CPUAccessFlags = 0;
index_buffer_desc.MiscFlags = 0;
index_buffer_desc.StructureByteStride = 0;
int32_t indices[6];
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 3;
indices[5] = 0;
D3D11_SUBRESOURCE_DATA index_buffer_data;
index_buffer_data.pSysMem = indices;
index_buffer_data.SysMemPitch = 0;
index_buffer_data.SysMemSlicePitch = 0;
hr = d3d11_device->CreateBuffer(&index_buffer_desc, &index_buffer_data, &index_buffer);

// during rendering I set:
unsigned int stride = sizeof(DirectX::XMFLOAT3);
unsigned int offset = 0;
d3d11_context->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset);
d3d11_context->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R32_UINT, 0);
d3d11_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
d3d11_context->RSSetState(rasterizer_state);
d3d11_context->IASetInputLayout(input_layout);
d3d11_context->VSSetShader(vertex_shader, NULL, 0);
d3d11_context->PSSetShader(pixel_shader,  NULL, 0);
// and render with:
d3d11_context->DrawIndexed(6, 0, 0);

Когда я смотрю на шейдеры с ID3D11ShaderReflection::GetGSInputPrimitive(), я получаю D3D_PRIMITIVE_UNDEFINED как для вершинного шейдера, так и для пиксельного шейдера.

Я устанавливаю этап растеризатора с помощью D3D11_FILL_SOLID и D3D11_CULL_NONE.

Есть ли какой-либо параметр или состояние в контексте D3D11, которые могли бы объяснить такое поведение? Я рад любым идеям, где искать. Заранее спасибо!


person Makx    schedule 17.01.2017    source источник
comment
может проблема в вызовах установки данных индекса/вершины? Возможно, нужно показать и их.   -  person MuertoExcobito    schedule 17.01.2017
comment
Спасибо за комментарий! Я добавил эту информацию к вопросу.   -  person Makx    schedule 17.01.2017
comment
Я не вижу ничего особенно плохого в вашем коде, хотя часто бывает трудно выделить такие ошибки, просто глядя на код. Я бы предложил запустить инструмент для отладки фреймов, такой как Windows Graphics Diagnostics, Nvidia Nsight и т. д.   -  person MuertoExcobito    schedule 17.01.2017
comment
Главное, на чем я хотел бы сосредоточиться, — это ваш порядок поворота лица для отбора лиц назад. Ваш код не включает ваши D3D11_RASTERIZER_DESC, в частности значения для CullMode, FillMode и FrontCounterClockwise. По умолчанию устройство для состояния растеризатора: D3D11_CULL_BACK, D3D11_FILL_SOLID и FALSE.   -  person Chuck Walbourn    schedule 17.01.2017
comment
Спасибо за комментарий. Как я писал в вопросе: я устанавливаю этап растеризатора с D3D11_FILL_SOLID и D3D11_CULL_NONE.   -  person Makx    schedule 19.01.2017


Ответы (2)


Во-первых, полоса треугольников рисует именно то, что вы ожидаете — последовательность треугольников. Каждый индекс в массиве индексов треугольника объединяется с двумя предыдущими индексами для создания треугольника.

Я бы предположил, что, поскольку ваш список треугольников не делится на 3, DirectX может отображаться неправильно (помните, что, поскольку это система с высокой пропускной способностью, она пропускает сдержки и противовесы, где это возможно, для повышения скорости).

Попробуйте нарисовать ожидаемые результаты на бумаге после изучения логики каждого из режимов рисования — список, полоса, веер и т. д., чтобы убедиться, что вы используете правильный порядок вершин и режим рисования.

Удачи!

person Monza    schedule 17.01.2017
comment
Спасибо за комментарий! Я также попытался установить индексный буфер на {0,1,2,0,2,3}. В моем понимании, это должно рисовать четырехугольник, как и полосу треугольника. Однако кажется, что он всегда рисует только одну линию между первыми двумя вершинами. - person Makx; 17.01.2017

Выяснилось, что проблема была не в коде. Где-то ранее что-то было изменено в состоянии Direct3D.

Звонок context->ClearState(); решил проблему.

person Makx    schedule 19.01.2017